diff --git a/core/corerepo/pinning.go b/core/corerepo/pinning.go index 0c30b5592..4cb1ec7f2 100644 --- a/core/corerepo/pinning.go +++ b/core/corerepo/pinning.go @@ -60,22 +60,21 @@ func Pin(n *core.IpfsNode, ctx context.Context, paths []string, recursive bool) func Unpin(n *core.IpfsNode, ctx context.Context, paths []string, recursive bool) ([]key.Key, error) { - dagnodes := make([]*merkledag.Node, 0) - for _, fpath := range paths { - dagnode, err := core.Resolve(ctx, n, path.Path(fpath)) + var unpinned []key.Key + for _, p := range paths { + p, err := path.ParsePath(p) if err != nil { return nil, err } - dagnodes = append(dagnodes, dagnode) - } - var unpinned []key.Key - for _, dagnode := range dagnodes { - k, _ := dagnode.Key() + k, err := core.ResolveToKey(ctx, n, p) + if err != nil { + return nil, err + } ctx, cancel := context.WithCancel(ctx) defer cancel() - err := n.Pinning.Unpin(ctx, k, recursive) + err = n.Pinning.Unpin(ctx, k, recursive) if err != nil { return nil, err } diff --git a/core/pathresolver.go b/core/pathresolver.go index 153f560bc..515899969 100644 --- a/core/pathresolver.go +++ b/core/pathresolver.go @@ -6,6 +6,7 @@ import ( context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context" + key "github.com/ipfs/go-ipfs/blocks/key" merkledag "github.com/ipfs/go-ipfs/merkledag" path "github.com/ipfs/go-ipfs/path" ) @@ -55,3 +56,31 @@ func Resolve(ctx context.Context, n *IpfsNode, p path.Path) (*merkledag.Node, er // ok, we have an ipfs path now (or what we'll treat as one) return n.Resolver.ResolvePath(ctx, p) } + +// ResolveToKey resolves a path to a key. +// +// It first checks if the path is already in the form of just a key ( or +// /ipfs/) and returns immediately if so. Otherwise, it falls back onto +// Resolve to perform resolution of the dagnode being referenced. +func ResolveToKey(ctx context.Context, n *IpfsNode, p path.Path) (key.Key, error) { + + // If the path is simply a key, parse and return it. Parsed paths are already + // normalized (read: prepended with /ipfs/ if needed), so segment[1] should + // always be the key. + if p.IsJustAKey() { + return key.B58KeyDecode(p.Segments()[1]), nil + } + + // Fall back onto regular dagnode resolution. + dagnode, err := Resolve(ctx, n, p) + if err != nil { + return key.Key(""), err + } + + // Extract and return the node's key. + k, err := dagnode.Key() + if err != nil { + return key.Key(""), err + } + return k, nil +} diff --git a/test/sharness/t0081-repo-pinning.sh b/test/sharness/t0081-repo-pinning.sh index f57a86303..be0e2e7ea 100755 --- a/test/sharness/t0081-repo-pinning.sh +++ b/test/sharness/t0081-repo-pinning.sh @@ -279,6 +279,13 @@ test_expect_success "test add nopin dir" ' ' +FICTIONAL_HASH="QmXV4f9v8a56MxWKBhP3ETsz4EaafudU1cKfPaaJnenc48" +test_launch_ipfs_daemon +test_expect_success "test unpinning a hash that's not pinned" " + test_expect_code 1 ipfs pin rm $FICTIONAL_HASH --timeout=5s +" +test_kill_ipfs_daemon + # test_kill_ipfs_daemon test_done