From eddd64119edbcaadc7e1de03e7134976bf2c8c1c Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Sun, 6 Sep 2015 12:49:25 -0700 Subject: [PATCH 1/8] Resolve '/ipfs/root/some/path' paths in 'ipfs resolve' command License: MIT Signed-off-by: Matt Bell --- core/commands/resolve.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/core/commands/resolve.go b/core/commands/resolve.go index e8c25a4c1..8917f2404 100644 --- a/core/commands/resolve.go +++ b/core/commands/resolve.go @@ -5,6 +5,7 @@ import ( "strings" cmds "github.com/ipfs/go-ipfs/commands" + context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context" namesys "github.com/ipfs/go-ipfs/namesys" path "github.com/ipfs/go-ipfs/path" u "github.com/ipfs/go-ipfs/util" @@ -78,6 +79,16 @@ Resolve the value of another name recursively: depth = namesys.DefaultDepthLimit } + 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 + } + output, err := n.Namesys.ResolveN(req.Context(), name, depth) if err != nil { res.SetError(err, cmds.ErrNormal) @@ -97,3 +108,22 @@ Resolve the value of another name recursively: }, Type: ResolvedPath{}, } + +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 +} From 8d370a39462d79c80df6573782520bd862cb2b4c Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Sun, 6 Sep 2015 12:55:37 -0700 Subject: [PATCH 2/8] Added help text to 'resolve' command to show DAG path resolution. License: MIT Signed-off-by: Matt Bell --- core/commands/resolve.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/commands/resolve.go b/core/commands/resolve.go index 8917f2404..de4eed143 100644 --- a/core/commands/resolve.go +++ b/core/commands/resolve.go @@ -47,6 +47,11 @@ Resolve the value of another name recursively: > ipfs resolve -r /ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj +Resolve the value of an IPFS DAG path: + + > ipfs resolve /ipfs/QmeZy1fGbwgVSrqbfh9fKQrAWgeyRnj7h8fsHS1oy3k99x/beep/boop + /ipfs/QmYRMjyvAiHKN9UTi8Bzt1HUspmSRD8T8DwxfSMzLgBon1 + `, }, From 3a2b83d904c51aebabf78de048cdf6651d7af279 Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Sun, 6 Sep 2015 16:00:35 -0700 Subject: [PATCH 3/8] resolve cmd: Fully resolve IPFS paths after resolving IPNS names License: MIT Signed-off-by: Matt Bell --- core/commands/resolve.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/core/commands/resolve.go b/core/commands/resolve.go index de4eed143..4ad255925 100644 --- a/core/commands/resolve.go +++ b/core/commands/resolve.go @@ -4,8 +4,8 @@ import ( "io" "strings" - cmds "github.com/ipfs/go-ipfs/commands" context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context" + cmds "github.com/ipfs/go-ipfs/commands" namesys "github.com/ipfs/go-ipfs/namesys" path "github.com/ipfs/go-ipfs/path" u "github.com/ipfs/go-ipfs/util" @@ -84,17 +84,22 @@ Resolve the value of an IPFS DAG path: depth = namesys.DefaultDepthLimit } + // for /ipfs/ paths, just parse the path + // for /ipns/ paths, resolve into a /ipfs/ path + var p path.Path 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}) + p, err = path.ParsePath(name) + } else { + p, err = n.Namesys.ResolveN(req.Context(), name, depth) + } + if err != nil { + res.SetError(err, cmds.ErrNormal) return } - output, err := n.Namesys.ResolveN(req.Context(), name, depth) + // 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) if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -114,12 +119,7 @@ Resolve the value of an IPFS DAG path: Type: ResolvedPath{}, } -func resolveIpfsPath (ctx context.Context, r *path.Resolver, name string) (path.Path, error) { - p, err := path.ParsePath(name) - if err != nil { - return "", err - } - +func resolveIpfsPath(ctx context.Context, r *path.Resolver, p path.Path) (path.Path, error) { node, err := r.ResolvePath(ctx, p) if err != nil { return "", err From 16e29dae77941d51847c8b03c1c868cab914fedb Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Sun, 6 Sep 2015 16:48:39 -0700 Subject: [PATCH 4/8] sharness: Added tests for 'ipfs resolve' License: MIT Signed-off-by: Matt Bell --- test/sharness/t0101-resolve.sh | 55 ++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100755 test/sharness/t0101-resolve.sh diff --git a/test/sharness/t0101-resolve.sh b/test/sharness/t0101-resolve.sh new file mode 100755 index 000000000..d4f51ab2b --- /dev/null +++ b/test/sharness/t0101-resolve.sh @@ -0,0 +1,55 @@ +#!/bin/sh +# +# Copyright (c) 2015 Matt Bell +# MIT Licensed; see the LICENSE file in this repository. +# + +test_description="Test ipfs resolve operations" + +. lib/test-lib.sh + +test_init_ipfs + +# setup + +test_expect_success "setup: add files" ' + mkdir mountdir/foodir && + echo "Hello Mars!" >mountdir/foodir/mars.txt && + echo "/ipfs/`ipfs add -q mountdir/foodir/mars.txt`" >filehash && + ipfs add -q -r mountdir/foodir | tail -n 1 >dirhash +' + +test_expect_success "setup: get IPFS ID" ' + ID=`ipfs id --format="\n"` +' + +# resolve an IPNS name to a simple /ipfs/ path + +test_expect_success "setup: publish file to IPNS name" ' + ipfs name publish `cat filehash` +' + +test_expect_success "'ipfs resolve' succeeds with IPNS->path" ' + echo `ipfs resolve "/ipns/$ID"` >actual +' + +test_expect_success "'ipfs resolve' output looks good" ' + test_cmp filehash actual +' + +# resolve an IPNS name to a /ipfs/HASH/link/name path + +test_expect_success "setup: publish link path to IPNS name" ' + ipfs name publish "`cat dirhash`/mars.txt" +' + +test_expect_success "'ipfs resolve' succeeds with IPNS->link path" ' + echo `ipfs resolve "/ipns/$ID"` >actual +' + +test_expect_success "'ipfs resolve' output looks good" ' + test_cmp filehash actual +' + + +test_done From dd8267b9e08d14103aeb5bf590a5b43038190090 Mon Sep 17 00:00:00 2001 From: Juan Batiz-Benet Date: Mon, 7 Sep 2015 02:12:01 +0200 Subject: [PATCH 5/8] resolve sharness test License: MIT Signed-off-by: Juan Batiz-Benet --- test/sharness/t0160-resolve.sh | 84 ++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100755 test/sharness/t0160-resolve.sh diff --git a/test/sharness/t0160-resolve.sh b/test/sharness/t0160-resolve.sh new file mode 100755 index 000000000..56df66a5d --- /dev/null +++ b/test/sharness/t0160-resolve.sh @@ -0,0 +1,84 @@ +#!/bin/sh + +test_description="Test resolve command" + +. lib/test-lib.sh + +test_init_ipfs + +test_expect_success "resolve: prepare files" ' + mkdir -p a/b && + echo "a/b/c" >a/b/c && + a_hash=$(ipfs add -q -r a | tail -n1) && + b_hash=$(ipfs add -q -r a/b | tail -n1) && + c_hash=$(ipfs add -q -r a/b/c | tail -n1) +' + +test_expect_success "resolve: prepare name" ' + id_hash=$(ipfs id -f="") && + ipfs name publish "$a_hash" && + printf "/ipfs/$a_hash" >expected_nameval && + ipfs name resolve >actual_nameval && + test_cmp expected_nameval actual_nameval +' + +test_resolve() { + src=$1 + dst=$2 + + test_expect_success "resolve succeeds: $src" ' + ipfs resolve "$src" >actual + ' + + test_expect_success "resolved correctly: $src -> $dst" ' + printf "$dst" >expected && + test_cmp expected actual + ' +} + +test_resolve_cmd() { + + test_resolve "/ipfs/$a_hash" "/ipfs/$a_hash" + test_resolve "/ipfs/$a_hash/b" "/ipfs/$b_hash" + test_resolve "/ipfs/$a_hash/b/c" "/ipfs/$c_hash" + + test_resolve "/ipns/$id_hash" "/ipfs/$a_hash" + test_resolve "/ipns/$id_hash/b" "/ipfs/$b_hash" + test_resolve "/ipns/$id_hash/b/c" "/ipfs/$c_hash" +} + +#todo remove this once the online resolve is fixed +test_resolve_fail() { + src=$1 + dst=$2 + + test_expect_failure "resolve succeeds: $src" ' + ipfs resolve "$src" >actual + ' + + test_expect_failure "resolved correctly: $src -> $dst" ' + printf "$dst" >expected && + test_cmp expected actual + ' +} + +test_resolve_cmd_fail() { + + test_resolve_fail "/ipfs/$a_hash" "/ipfs/$a_hash" + test_resolve_fail "/ipfs/$a_hash/b" "/ipfs/$b_hash" + test_resolve_fail "/ipfs/$a_hash/b/c" "/ipfs/$c_hash" + + test_resolve_fail "/ipns/$id_hash" "/ipfs/$a_hash" + test_resolve_fail "/ipns/$id_hash/b" "/ipfs/$b_hash" + test_resolve_fail "/ipns/$id_hash/b/c" "/ipfs/$c_hash" +} + +# should work offline +test_resolve_cmd + +# should work online +test_launch_ipfs_daemon +test_resolve_cmd_fail +test_kill_ipfs_daemon + +test_done From 04482cbe41b440676230f1c20482496ae6c5c59e Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Mon, 7 Sep 2015 14:14:50 -0700 Subject: [PATCH 6/8] Consolidated 'resolve' tests License: MIT Signed-off-by: Matt Bell --- test/sharness/t0101-resolve.sh | 55 -------------------------------- test/sharness/t0160-resolve.sh | 57 +++++++++++++++++++++++++++------- 2 files changed, 45 insertions(+), 67 deletions(-) delete mode 100755 test/sharness/t0101-resolve.sh diff --git a/test/sharness/t0101-resolve.sh b/test/sharness/t0101-resolve.sh deleted file mode 100755 index d4f51ab2b..000000000 --- a/test/sharness/t0101-resolve.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2015 Matt Bell -# MIT Licensed; see the LICENSE file in this repository. -# - -test_description="Test ipfs resolve operations" - -. lib/test-lib.sh - -test_init_ipfs - -# setup - -test_expect_success "setup: add files" ' - mkdir mountdir/foodir && - echo "Hello Mars!" >mountdir/foodir/mars.txt && - echo "/ipfs/`ipfs add -q mountdir/foodir/mars.txt`" >filehash && - ipfs add -q -r mountdir/foodir | tail -n 1 >dirhash -' - -test_expect_success "setup: get IPFS ID" ' - ID=`ipfs id --format="\n"` -' - -# resolve an IPNS name to a simple /ipfs/ path - -test_expect_success "setup: publish file to IPNS name" ' - ipfs name publish `cat filehash` -' - -test_expect_success "'ipfs resolve' succeeds with IPNS->path" ' - echo `ipfs resolve "/ipns/$ID"` >actual -' - -test_expect_success "'ipfs resolve' output looks good" ' - test_cmp filehash actual -' - -# resolve an IPNS name to a /ipfs/HASH/link/name path - -test_expect_success "setup: publish link path to IPNS name" ' - ipfs name publish "`cat dirhash`/mars.txt" -' - -test_expect_success "'ipfs resolve' succeeds with IPNS->link path" ' - echo `ipfs resolve "/ipns/$ID"` >actual -' - -test_expect_success "'ipfs resolve' output looks good" ' - test_cmp filehash actual -' - - -test_done diff --git a/test/sharness/t0160-resolve.sh b/test/sharness/t0160-resolve.sh index 56df66a5d..02b457c54 100755 --- a/test/sharness/t0160-resolve.sh +++ b/test/sharness/t0160-resolve.sh @@ -14,20 +14,36 @@ test_expect_success "resolve: prepare files" ' c_hash=$(ipfs add -q -r a/b/c | tail -n1) ' -test_expect_success "resolve: prepare name" ' - id_hash=$(ipfs id -f="") && - ipfs name publish "$a_hash" && - printf "/ipfs/$a_hash" >expected_nameval && - ipfs name resolve >actual_nameval && - test_cmp expected_nameval actual_nameval -' +test_resolve_setup_name() { + ref=$1 + + test_expect_success "resolve: prepare name" ' + id_hash=$(ipfs id -f="") && + ipfs name publish "$ref" && + printf "$ref" >expected_nameval && + ipfs name resolve >actual_nameval && + test_cmp expected_nameval actual_nameval + ' +} + +test_resolve_setup_name_fail() { + ref=$1 + + test_expect_failure "resolve: prepare name" ' + id_hash=$(ipfs id -f="") && + ipfs name publish "$ref" && + printf "$ref" >expected_nameval && + ipfs name resolve >actual_nameval && + test_cmp expected_nameval actual_nameval + ' +} test_resolve() { src=$1 dst=$2 test_expect_success "resolve succeeds: $src" ' - ipfs resolve "$src" >actual + ipfs resolve -r "$src" >actual ' test_expect_success "resolved correctly: $src -> $dst" ' @@ -41,10 +57,19 @@ test_resolve_cmd() { test_resolve "/ipfs/$a_hash" "/ipfs/$a_hash" test_resolve "/ipfs/$a_hash/b" "/ipfs/$b_hash" test_resolve "/ipfs/$a_hash/b/c" "/ipfs/$c_hash" + test_resolve "/ipfs/$b_hash/c" "/ipfs/$c_hash" + test_resolve_setup_name "/ipfs/$a_hash" test_resolve "/ipns/$id_hash" "/ipfs/$a_hash" test_resolve "/ipns/$id_hash/b" "/ipfs/$b_hash" test_resolve "/ipns/$id_hash/b/c" "/ipfs/$c_hash" + + test_resolve_setup_name "/ipfs/$b_hash" + test_resolve "/ipns/$id_hash" "/ipfs/$b_hash" + test_resolve "/ipns/$id_hash/c" "/ipfs/$c_hash" + + test_resolve_setup_name "/ipfs/$c_hash" + test_resolve "/ipns/$id_hash" "/ipfs/$c_hash" } #todo remove this once the online resolve is fixed @@ -63,14 +88,22 @@ test_resolve_fail() { } test_resolve_cmd_fail() { + test_resolve "/ipfs/$a_hash" "/ipfs/$a_hash" + test_resolve "/ipfs/$a_hash/b" "/ipfs/$b_hash" + test_resolve "/ipfs/$a_hash/b/c" "/ipfs/$c_hash" + test_resolve "/ipfs/$b_hash/c" "/ipfs/$c_hash" - test_resolve_fail "/ipfs/$a_hash" "/ipfs/$a_hash" - test_resolve_fail "/ipfs/$a_hash/b" "/ipfs/$b_hash" - test_resolve_fail "/ipfs/$a_hash/b/c" "/ipfs/$c_hash" - + test_resolve_setup_name_fail "/ipfs/$a_hash" test_resolve_fail "/ipns/$id_hash" "/ipfs/$a_hash" test_resolve_fail "/ipns/$id_hash/b" "/ipfs/$b_hash" test_resolve_fail "/ipns/$id_hash/b/c" "/ipfs/$c_hash" + + test_resolve_setup_name_fail "/ipfs/$b_hash" + test_resolve_fail "/ipns/$id_hash" "/ipfs/$b_hash" + test_resolve_fail "/ipns/$id_hash/c" "/ipfs/$c_hash" + + test_resolve_setup_name_fail "/ipfs/$c_hash" + test_resolve_fail "/ipns/$id_hash" "/ipfs/$c_hash" } # should work offline From 2e0c072dac3b0d08ac3abe3bc1af5d2850caa677 Mon Sep 17 00:00:00 2001 From: rht Date: Tue, 13 Oct 2015 16:14:41 +0700 Subject: [PATCH 7/8] Use core path resolver for 'resolve command' [1] [1] https://github.com/ipfs/go-ipfs/commit/172eeb87fa2301d7f52c5ecb28f37f5d06126c29 License: MIT Signed-off-by: rht --- core/commands/resolve.go | 52 ++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/core/commands/resolve.go b/core/commands/resolve.go index 4ad255925..f6ad91eae 100644 --- a/core/commands/resolve.go +++ b/core/commands/resolve.go @@ -4,9 +4,8 @@ import ( "io" "strings" - context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context" cmds "github.com/ipfs/go-ipfs/commands" - namesys "github.com/ipfs/go-ipfs/namesys" + "github.com/ipfs/go-ipfs/core" path "github.com/ipfs/go-ipfs/path" u "github.com/ipfs/go-ipfs/util" ) @@ -79,33 +78,38 @@ Resolve the value of an IPFS DAG path: name := req.Arguments()[0] recursive, _, _ := req.Option("recursive").Bool() - depth := 1 - if recursive { - depth = namesys.DefaultDepthLimit + + // the case when ipns is resolved step by step + if strings.HasPrefix(name, "/ipns/") && !recursive { + p, err := n.Namesys.ResolveN(req.Context(), name, 1) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + res.SetOutput(&ResolvedPath{p}) + return } - // for /ipfs/ paths, just parse the path - // for /ipns/ paths, resolve into a /ipfs/ path - var p path.Path - if strings.HasPrefix(name, "/ipfs/") || !strings.HasPrefix(name, "/") { - p, err = path.ParsePath(name) - } else { - p, err = n.Namesys.ResolveN(req.Context(), name, depth) - } + // else, ipfs path or ipns with recursive flag + p, err := path.ParsePath(name) if err != nil { res.SetError(err, cmds.ErrNormal) return } - // 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) + node, err := core.Resolve(req.Context(), n, p) if err != nil { res.SetError(err, cmds.ErrNormal) return } - res.SetOutput(&ResolvedPath{output}) + key, err := node.Key() + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + + res.SetOutput(&ResolvedPath{path.FromKey(key)}) }, Marshalers: cmds.MarshalerMap{ cmds.Text: func(res cmds.Response) (io.Reader, error) { @@ -118,17 +122,3 @@ Resolve the value of an IPFS DAG path: }, Type: ResolvedPath{}, } - -func resolveIpfsPath(ctx context.Context, r *path.Resolver, p path.Path) (path.Path, error) { - 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 -} From 740447eecdc7c4fb58ec220d3b68d542c885cb9e Mon Sep 17 00:00:00 2001 From: rht Date: Tue, 13 Oct 2015 16:15:56 +0700 Subject: [PATCH 8/8] Fix typo License: MIT Signed-off-by: rht --- core/pathresolver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/pathresolver.go b/core/pathresolver.go index 610eeb50b..153f560bc 100644 --- a/core/pathresolver.go +++ b/core/pathresolver.go @@ -17,7 +17,7 @@ var ErrNoNamesys = errors.New( // Resolve resolves the given path by parsing out protocol-specific // entries (e.g. /ipns/) and then going through the /ipfs/ -// entries and returning the final merkledage node. Effectively +// entries and returning the final merkledag node. Effectively // enables /ipns/, /dns/, etc. in commands. func Resolve(ctx context.Context, n *IpfsNode, p path.Path) (*merkledag.Node, error) { if strings.HasPrefix(p.String(), "/ipns/") {