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

import (
4 5
	"io"
	"strings"
6

7
	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
8
	cmds "github.com/ipfs/go-ipfs/commands"
9
	namesys "github.com/ipfs/go-ipfs/namesys"
10
	path "github.com/ipfs/go-ipfs/path"
11
	u "github.com/ipfs/go-ipfs/util"
12 13
)

14 15
type ResolvedPath struct {
	Path path.Path
16 17
}

18
var ResolveCmd = &cmds.Command{
19
	Helptext: cmds.HelpText{
20
		Tagline: "Resolve the value of names to IPFS",
21
		ShortDescription: `
22 23 24
There are a number of mutable name protocols that can link among
themselves and into IPNS.  This command accepts any of these
identifiers and resolves them to the referenced item.
25 26
`,
		LongDescription: `
27 28 29 30 31
There are a number of mutable name protocols that can link among
themselves and into IPNS.  For example IPNS references can (currently)
point at IPFS object, and DNS links can point at other DNS links, IPNS
entries, or IPFS objects.  This command accepts any of these
identifiers and resolves them to the referenced item.
32 33 34 35 36

Examples:

Resolve the value of your identity:

37 38 39 40 41 42 43
  > ipfs resolve /ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
  /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj

Resolve the value of another name:

  > ipfs resolve /ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n
  /ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
44

45
Resolve the value of another name recursively:
46

47 48
  > ipfs resolve -r /ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n
  /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj
49

50 51 52 53 54
Resolve the value of an IPFS DAG path:

  > ipfs resolve /ipfs/QmeZy1fGbwgVSrqbfh9fKQrAWgeyRnj7h8fsHS1oy3k99x/beep/boop
  /ipfs/QmYRMjyvAiHKN9UTi8Bzt1HUspmSRD8T8DwxfSMzLgBon1

55
`,
56
	},
57 58

	Arguments: []cmds.Argument{
59
		cmds.StringArg("name", true, false, "The name to resolve.").EnableStdin(),
60
	},
61
	Options: []cmds.Option{
62
		cmds.BoolOption("recursive", "r", "Resolve until the result is an IPFS name"),
63
	},
64
	Run: func(req cmds.Request, res cmds.Response) {
65

Jeromy's avatar
Jeromy committed
66
		n, err := req.InvocContext().GetNode()
67
		if err != nil {
68 69
			res.SetError(err, cmds.ErrNormal)
			return
70 71
		}

72 73 74 75 76 77
		if !n.OnlineMode() {
			err := n.SetupOfflineRouting()
			if err != nil {
				res.SetError(err, cmds.ErrNormal)
				return
			}
78 79
		}

80
		name := req.Arguments()[0]
81 82 83 84 85 86
		recursive, _, _ := req.Option("recursive").Bool()
		depth := 1
		if recursive {
			depth = namesys.DefaultDepthLimit
		}

87 88 89
		// for /ipfs/ paths, just parse the path
		// for /ipns/ paths, resolve into a /ipfs/ path
		var p path.Path
90
		if strings.HasPrefix(name, "/ipfs/") || !strings.HasPrefix(name, "/") {
91 92 93 94 95 96
			p, err = path.ParsePath(name)
		} else {
			p, err = n.Namesys.ResolveN(req.Context(), name, depth)
		}
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
97 98 99
			return
		}

100 101 102
		// now fully resolve the /ipfs/ path
		// (walk DAG links if there is a path of link names)
		output, err := resolveIpfsPath(req.Context(), n.Resolver, p)
103
		if err != nil {
104 105
			res.SetError(err, cmds.ErrNormal)
			return
106 107
		}

108
		res.SetOutput(&ResolvedPath{output})
109
	},
110
	Marshalers: cmds.MarshalerMap{
111
		cmds.Text: func(res cmds.Response) (io.Reader, error) {
112
			output, ok := res.Output().(*ResolvedPath)
113 114 115
			if !ok {
				return nil, u.ErrCast()
			}
116
			return strings.NewReader(output.Path.String()), nil
117
		},
118
	},
119
	Type: ResolvedPath{},
120
}
121

122
func resolveIpfsPath(ctx context.Context, r *path.Resolver, p path.Path) (path.Path, error) {
123 124 125 126 127 128 129 130 131 132 133 134
	node, err := r.ResolvePath(ctx, p)
	if err != nil {
		return "", err
	}

	key, err := node.Key()
	if err != nil {
		return "", err
	}

	return path.FromKey(key), nil
}