diff --git a/core/commands/cat.go b/core/commands/cat.go index 3a4899746be6754e1127c3fdcc1ec6561d9b72fd..2132cb616bee5fbf05c8ce5dee33d778e26337f5 100644 --- a/core/commands/cat.go +++ b/core/commands/cat.go @@ -18,7 +18,7 @@ var CatCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Show IPFS object data", ShortDescription: ` -Retrieves the object named by <ipfs-path> and outputs the data +Retrieves the object named by <ipfs-or-ipns-path> and outputs the data it contains. `, }, @@ -62,7 +62,7 @@ func cat(ctx context.Context, node *core.IpfsNode, paths []string) ([]io.Reader, readers := make([]io.Reader, 0, len(paths)) length := uint64(0) for _, fpath := range paths { - dagnode, err := node.Resolver.ResolvePath(path.Path(fpath)) + dagnode, err := core.Resolve(node, path.Path(fpath)) if err != nil { return nil, 0, err } diff --git a/core/commands/get.go b/core/commands/get.go index f0d6bb7c0903fdf4b08c792a68026e8fadef8b39..74ad0fbaa7d4a0dba089418b460825196b8b67c9 100644 --- a/core/commands/get.go +++ b/core/commands/get.go @@ -24,7 +24,7 @@ var GetCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Download IPFS objects", ShortDescription: ` -Retrieves the object named by <ipfs-path> and stores the data to disk. +Retrieves the object named by <ipfs-or-ipns-path> and stores the data to disk. By default, the output will be stored at ./<ipfs-path>, but an alternate path can be specified with '--output=<path>' or '-o=<path>'. @@ -166,5 +166,11 @@ func getCompressOptions(req cmds.Request) (int, error) { } func get(node *core.IpfsNode, p string, compression int) (io.Reader, error) { - return utar.NewReader(path.Path(p), node.DAG, node.Resolver, compression) + pathToResolve := path.Path(p) + dagnode, err := core.Resolve(node, pathToResolve) + if err != nil { + return nil, err + } + + return utar.NewReader(pathToResolve, node.DAG, dagnode, compression) } diff --git a/core/commands/ls.go b/core/commands/ls.go index a251326a6a68cf59ca2f55d85e8f3a99903ea3b8..9917426e1f2c52c62195c3427f8cc08ef8712de5 100644 --- a/core/commands/ls.go +++ b/core/commands/ls.go @@ -10,9 +10,10 @@ import ( context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context" cmds "github.com/ipfs/go-ipfs/commands" + core "github.com/ipfs/go-ipfs/core" merkledag "github.com/ipfs/go-ipfs/merkledag" path "github.com/ipfs/go-ipfs/path" - "github.com/ipfs/go-ipfs/unixfs" + unixfs "github.com/ipfs/go-ipfs/unixfs" unixfspb "github.com/ipfs/go-ipfs/unixfs/pb" ) @@ -35,7 +36,7 @@ var LsCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "List links from an object.", ShortDescription: ` -Retrieves the object named by <ipfs-path> and displays the links +Retrieves the object named by <ipfs-or-ipns-path> and displays the links it contains, with the following format: <link base58 hash> <link size in bytes> <link name> @@ -65,7 +66,7 @@ it contains, with the following format: dagnodes := make([]*merkledag.Node, 0) for _, fpath := range paths { - dagnode, err := node.Resolver.ResolvePath(path.Path(fpath)) + dagnode, err := core.Resolve(node, path.Path(fpath)) if err != nil { res.SetError(err, cmds.ErrNormal) return diff --git a/core/commands/object.go b/core/commands/object.go index b45ee4667eeb1815a660a1649c312055a30ac645..e4400199b3973690583c3265a46ffada7cc52687 100644 --- a/core/commands/object.go +++ b/core/commands/object.go @@ -345,7 +345,7 @@ Data should be in the format specified by the --inputenc flag. // objectData takes a key string and writes out the raw bytes of that node (if there is one) func objectData(n *core.IpfsNode, fpath path.Path) (io.Reader, error) { - dagnode, err := n.Resolver.ResolvePath(fpath) + dagnode, err := core.Resolve(n, fpath) if err != nil { return nil, err } @@ -357,7 +357,7 @@ func objectData(n *core.IpfsNode, fpath path.Path) (io.Reader, error) { // objectLinks takes a key string and lists the links it points to func objectLinks(n *core.IpfsNode, fpath path.Path) (*Object, error) { - dagnode, err := n.Resolver.ResolvePath(fpath) + dagnode, err := core.Resolve(n, fpath) if err != nil { return nil, err } @@ -369,7 +369,7 @@ func objectLinks(n *core.IpfsNode, fpath path.Path) (*Object, error) { // objectGet takes a key string from args and a format option and serializes the dagnode to that format func objectGet(n *core.IpfsNode, fpath path.Path) (*dag.Node, error) { - dagnode, err := n.Resolver.ResolvePath(fpath) + dagnode, err := core.Resolve(n, fpath) if err != nil { return nil, err } diff --git a/core/commands/refs.go b/core/commands/refs.go index 67436c6ffb76777e0a6ed63c5ed9ea0cfa0f3f67..f6df161537a74f82b69347e962dba3f3f8121566 100644 --- a/core/commands/refs.go +++ b/core/commands/refs.go @@ -164,7 +164,7 @@ Displays the hashes of all local objects. func objectsForPaths(n *core.IpfsNode, paths []string) ([]*dag.Node, error) { objects := make([]*dag.Node, len(paths)) for i, p := range paths { - o, err := n.Resolver.ResolvePath(path.Path(p)) + o, err := core.Resolve(n, path.Path(p)) if err != nil { return nil, err } diff --git a/core/core.go b/core/core.go index 0add895251487a1cdc7bc577a39e2c1ae814f101..ca7abf36e6375977567297f0c9655713b9cd4a6a 100644 --- a/core/core.go +++ b/core/core.go @@ -345,10 +345,6 @@ func (n *IpfsNode) OnlineMode() bool { } } -func (n *IpfsNode) Resolve(fpath string) (*merkledag.Node, error) { - return n.Resolver.ResolvePath(path.Path(fpath)) -} - func (n *IpfsNode) Bootstrap(cfg BootstrapConfig) error { // TODO what should return value be when in offlineMode? diff --git a/core/corerepo/pinning.go b/core/corerepo/pinning.go index 804ec746c6dc42c82234da9df697eb872a5e994d..81acba43e7d284dd34d17b7924eb40e1b49be52f 100644 --- a/core/corerepo/pinning.go +++ b/core/corerepo/pinning.go @@ -16,7 +16,7 @@ func Pin(n *core.IpfsNode, paths []string, recursive bool) ([]u.Key, error) { dagnodes := make([]*merkledag.Node, 0) for _, fpath := range paths { - dagnode, err := n.Resolver.ResolvePath(path.Path(fpath)) + dagnode, err := core.Resolve(n, path.Path(fpath)) if err != nil { return nil, fmt.Errorf("pin: %s", err) } @@ -51,7 +51,7 @@ func Unpin(n *core.IpfsNode, paths []string, recursive bool) ([]u.Key, error) { dagnodes := make([]*merkledag.Node, 0) for _, fpath := range paths { - dagnode, err := n.Resolver.ResolvePath(path.Path(fpath)) + dagnode, err := core.Resolve(n, path.Path(fpath)) if err != nil { return nil, err } diff --git a/core/pathresolver.go b/core/pathresolver.go new file mode 100644 index 0000000000000000000000000000000000000000..c84821ce718a12485bef423be9edc8e9ebf5218c --- /dev/null +++ b/core/pathresolver.go @@ -0,0 +1,40 @@ +package core + +import ( + merkledag "github.com/ipfs/go-ipfs/merkledag" + path "github.com/ipfs/go-ipfs/path" + "strings" +) + +// Resolves the given path by parsing out /ipns/ entries and then going +// through the /ipfs/ entries and returning the final merkledage node. +// Effectively enables /ipns/ in CLI commands. +func Resolve(n *IpfsNode, p path.Path) (*merkledag.Node, error) { + strpath := string(p) + + // for now, we only try to resolve ipns paths if + // they begin with "/ipns/". Otherwise, ambiguity + // emerges when resolving just a <hash>. Is it meant + // to be an ipfs or an ipns resolution? + + if strings.HasPrefix(strpath, "/ipns/") { + // if it's an ipns path, try to resolve it. + // if we can't, we can give that error back to the user. + ipnsPath := p.Segments()[1] + extensions := p.Segments()[2:] + key, err := n.Namesys.Resolve(n.Context(), ipnsPath) + if err != nil { + return nil, err + } + + pathHead := make([]string, 2) + pathHead[0] = "ipfs" + pathHead[1] = key.Pretty() + + p = path.FromSegments(append(pathHead, extensions...)...) + //p = path.RebasePath(path.FromSegments(extensions...), basePath) + } + + // ok, we have an ipfs path now (or what we'll treat as one) + return n.Resolver.ResolvePath(p) +} diff --git a/path/path.go b/path/path.go index ea83cd12ceb118529164047c0ecab6e0e7094d9c..7820880c17216fafc6957c52fc35859ca8fb2eee 100644 --- a/path/path.go +++ b/path/path.go @@ -1,10 +1,9 @@ package path import ( + u "github.com/ipfs/go-ipfs/util" "path" "strings" - - u "github.com/ipfs/go-ipfs/util" ) // TODO: debate making this a private struct wrapped in a public interface @@ -36,3 +35,7 @@ func (p Path) Segments() []string { func (p Path) String() string { return string(p) } + +func FromSegments(seg ...string) Path { + return Path(strings.Join(seg, "/")) +} diff --git a/unixfs/tar/reader.go b/unixfs/tar/reader.go index 9509b2d6dc645a4ecd27bdd73f7fda9ded7c0628..405a0eb187acf80e86ea1ac4fc3b661494ed6aa5 100644 --- a/unixfs/tar/reader.go +++ b/unixfs/tar/reader.go @@ -28,12 +28,11 @@ type Reader struct { err error } -func NewReader(path path.Path, dag mdag.DAGService, resolver *path.Resolver, compression int) (*Reader, error) { +func NewReader(path path.Path, dag mdag.DAGService, dagnode *mdag.Node, compression int) (*Reader, error) { reader := &Reader{ signalChan: make(chan struct{}), dag: dag, - resolver: resolver, } var err error @@ -47,11 +46,6 @@ func NewReader(path path.Path, dag mdag.DAGService, resolver *path.Resolver, com reader.writer = tar.NewWriter(&reader.buf) } - dagnode, err := resolver.ResolvePath(path) - if err != nil { - return nil, err - } - // writeToBuf will write the data to the buffer, and will signal when there // is new data to read _, filename := gopath.Split(path.String())