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

import (
4 5
	"io"
	"strings"
6

7
	cmds "github.com/ipfs/go-ipfs/commands"
8
	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
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 90 91 92 93 94 95 96
		if strings.HasPrefix(name, "/ipfs/") || !strings.HasPrefix(name, "/") {
			resolved, err := resolveIpfsPath(req.Context(), n.Resolver, name)
			if err != nil {
				res.SetError(err, cmds.ErrNormal)
				return
			}
			res.SetOutput(&ResolvedPath{resolved})
			return
		}

Jeromy's avatar
Jeromy committed
97
		output, err := n.Namesys.ResolveN(req.Context(), name, depth)
98
		if err != nil {
99 100
			res.SetError(err, cmds.ErrNormal)
			return
101 102
		}

103
		res.SetOutput(&ResolvedPath{output})
104
	},
105
	Marshalers: cmds.MarshalerMap{
106
		cmds.Text: func(res cmds.Response) (io.Reader, error) {
107
			output, ok := res.Output().(*ResolvedPath)
108 109 110
			if !ok {
				return nil, u.ErrCast()
			}
111
			return strings.NewReader(output.Path.String()), nil
112
		},
113
	},
114
	Type: ResolvedPath{},
115
}
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134

func resolveIpfsPath (ctx context.Context, r *path.Resolver, name string) (path.Path, error) {
	p, err := path.ParsePath(name)
	if err != nil {
		return "", err
	}

	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
}