mirror of
https://github.com/ipfs/kubo.git
synced 2025-06-30 18:13:54 +08:00
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>
This commit is contained in:
@ -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
|
||||
}
|
||||
|
@ -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 (<key> or
|
||||
// /ipfs/<key>) 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
|
||||
}
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user