@cryptotaxi247 / kubo / commits / 32ceaa61e

Resolves paths in 'pin rm' without network lookup.

Fixes ipfs/go-ipfs#2155 by turning the hash path arguments into keys and unpinning directly, rather than running a full core.Resolve on them. This lets users fail fast when they try to remove pins that they don't have locally. Note that this will only work when the path is of the form <hash> or /ipfs/<hash>. Given e.g. /ipfs/<hash>/foo, foo's key cannot be known without first resolving <hash>, which may involve talking to the network. License: MIT Signed-off-by: Stephen Whitmore <noffle@ipfs.io>

Stephen Whitmore committed Jan 16, 2016 at 03:11 UTC 32ceaa61e81a7e0e9d53ea3a9a78e4f101fb58ea
3 files changed +44 -9
core/corerepo/pinning.go
+8 -9
@@ -60,22 +60,21 @@ func Pin(n *core.IpfsNode, ctx context.Context, paths []string, recursive bool)
60
61 func Unpin(n *core.IpfsNode, ctx context.Context, paths []string, recursive bool) ([]key.Key, error) {
62
63 - dagnodes := make([]*merkledag.Node, 0)
64 - for _, fpath := range paths {
65 - dagnode, err := core.Resolve(ctx, n, path.Path(fpath))
63 + var unpinned []key.Key
64 + for _, p := range paths {
65 + p, err := path.ParsePath(p)
66 if err != nil {
67 return nil, err
68 }
69 - dagnodes = append(dagnodes, dagnode)
70 - }
69
72 - var unpinned []key.Key
73 - for _, dagnode := range dagnodes {
74 - k, _ := dagnode.Key()
70 + k, err := core.ResolveToKey(ctx, n, p)
71 + if err != nil {
72 + return nil, err
73 + }
74
75 ctx, cancel := context.WithCancel(ctx)
76 defer cancel()
78 - err := n.Pinning.Unpin(ctx, k, recursive)
77 + err = n.Pinning.Unpin(ctx, k, recursive)
78 if err != nil {
79 return nil, err
80 }
core/pathresolver.go
+29
@@ -6,6 +6,7 @@ import (
6
7 context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
8
9 + key "github.com/ipfs/go-ipfs/blocks/key"
10 merkledag "github.com/ipfs/go-ipfs/merkledag"
11 path "github.com/ipfs/go-ipfs/path"
12 )
@@ -55,3 +56,31 @@ func Resolve(ctx context.Context, n *IpfsNode, p path.Path) (*merkledag.Node, er
56 // ok, we have an ipfs path now (or what we'll treat as one)
57 return n.Resolver.ResolvePath(ctx, p)
58 }
59 +
60 +// ResolveToKey resolves a path to a key.
61 +//
62 +// It first checks if the path is already in the form of just a key (<key> or
63 +// /ipfs/<key>) and returns immediately if so. Otherwise, it falls back onto
64 +// Resolve to perform resolution of the dagnode being referenced.
65 +func ResolveToKey(ctx context.Context, n *IpfsNode, p path.Path) (key.Key, error) {
66 +
67 + // If the path is simply a key, parse and return it. Parsed paths are already
68 + // normalized (read: prepended with /ipfs/ if needed), so segment[1] should
69 + // always be the key.
70 + if p.IsJustAKey() {
71 + return key.B58KeyDecode(p.Segments()[1]), nil
72 + }
73 +
74 + // Fall back onto regular dagnode resolution.
75 + dagnode, err := Resolve(ctx, n, p)
76 + if err != nil {
77 + return key.Key(""), err
78 + }
79 +
80 + // Extract and return the node's key.
81 + k, err := dagnode.Key()
82 + if err != nil {
83 + return key.Key(""), err
84 + }
85 + return k, nil
86 +}
test/sharness/t0081-repo-pinning.sh
+7
@@ -279,6 +279,13 @@ test_expect_success "test add nopin dir" '
279
280 '
281
282 +FICTIONAL_HASH="QmXV4f9v8a56MxWKBhP3ETsz4EaafudU1cKfPaaJnenc48"
283 +test_launch_ipfs_daemon
284 +test_expect_success "test unpinning a hash that's not pinned" "
285 + test_expect_code 1 ipfs pin rm $FICTIONAL_HASH --timeout=5s
286 +"
287 +test_kill_ipfs_daemon
288 +
289 # test_kill_ipfs_daemon
290
291 test_done