From b770c881a790dd860070de8e4e980fd835471a72 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sat, 16 Jan 2016 14:37:04 +0100 Subject: [PATCH 1/8] pin/pin: replace isPinned() with isPinnedWithType() It is more generic to be able to pass a pin type argument. License: MIT Signed-off-by: Christian Couder --- pin/pin.go | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/pin/pin.go b/pin/pin.go index 4cb2b2c68b9..86b0d58daa8 100644 --- a/pin/pin.go +++ b/pin/pin.go @@ -36,6 +36,7 @@ const ( type Pinner interface { IsPinned(key.Key) (string, bool, error) + IsPinnedWithType(key.Key, string) (string, bool, error) Pin(context.Context, *mdag.Node, bool) error Unpin(context.Context, key.Key, bool) error @@ -126,7 +127,7 @@ func (p *pinner) Pin(ctx context.Context, node *mdag.Node, recurse bool) error { func (p *pinner) Unpin(ctx context.Context, k key.Key, recursive bool) error { p.lock.Lock() defer p.lock.Unlock() - reason, pinned, err := p.isPinned(k) + reason, pinned, err := p.isPinnedWithType(k, "all") if err != nil { return err } @@ -159,22 +160,46 @@ func (p *pinner) isInternalPin(key key.Key) bool { func (p *pinner) IsPinned(k key.Key) (string, bool, error) { p.lock.RLock() defer p.lock.RUnlock() - return p.isPinned(k) + return p.isPinnedWithType(k, "all") } -// isPinned is the implementation of IsPinned that does not lock. +func (p *pinner) IsPinnedWithType(k key.Key, typeStr string) (string, bool, error) { + p.lock.RLock() + defer p.lock.RUnlock() + return p.isPinnedWithType(k, typeStr) +} + +// isPinnedWithType is the implementation of IsPinnedWithType that does not lock. // intended for use by other pinned methods that already take locks -func (p *pinner) isPinned(k key.Key) (string, bool, error) { - if p.recursePin.HasKey(k) { +func (p *pinner) isPinnedWithType(k key.Key, typeStr string) (string, bool, error) { + switch typeStr { + case "all", "direct", "indirect", "recursive", "internal": + default: + err := fmt.Errorf("Invalid type '%s', must be one of {direct, indirect, recursive, internal, all}", typeStr) + return "", false, err + } + if (typeStr == "recursive" || typeStr == "all") && p.recursePin.HasKey(k) { return "recursive", true, nil } - if p.directPin.HasKey(k) { + if typeStr == "recursive" { + return "", false, nil + } + + if (typeStr == "direct" || typeStr == "all") && p.directPin.HasKey(k) { return "direct", true, nil } - if p.isInternalPin(k) { + if typeStr == "direct" { + return "", false, nil + } + + if (typeStr == "internal" || typeStr == "all") && p.isInternalPin(k) { return "internal", true, nil } + if typeStr == "internal" { + return "", false, nil + } + // Default is "indirect" for _, rk := range p.recursePin.GetKeys() { rnd, err := p.dserv.Get(context.Background(), rk) if err != nil { From c89e3c22ebb54ad26e3f93d94fe084aa0b7c0edc Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 12 Jan 2016 21:54:37 +0100 Subject: [PATCH 2/8] core/commands/pin: refactor 'pin ls' License: MIT Signed-off-by: Christian Couder --- core/commands/pin.go | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/core/commands/pin.go b/core/commands/pin.go index e6155df9c00..9b595e38158 100644 --- a/core/commands/pin.go +++ b/core/commands/pin.go @@ -212,13 +212,18 @@ Example: } keys := make(map[string]RefKeyObject) - if typeStr == "direct" || typeStr == "all" { - for _, k := range n.Pinning.DirectKeys() { + + AddToResultKeys := func(keyList []key.Key, typeStr string) { + for _, k := range keyList { keys[k.B58String()] = RefKeyObject{ - Type: "direct", + Type: typeStr, } } } + + if typeStr == "direct" || typeStr == "all" { + AddToResultKeys(n.Pinning.DirectKeys(), "direct") + } if typeStr == "indirect" || typeStr == "all" { ks := key.NewKeySet() for _, k := range n.Pinning.RecursiveKeys() { @@ -232,20 +237,11 @@ Example: res.SetError(err, cmds.ErrNormal) return } - - } - for _, k := range ks.Keys() { - keys[k.B58String()] = RefKeyObject{ - Type: "indirect", - } } + AddToResultKeys(ks.Keys(), "indirect") } if typeStr == "recursive" || typeStr == "all" { - for _, k := range n.Pinning.RecursiveKeys() { - keys[k.B58String()] = RefKeyObject{ - Type: "recursive", - } - } + AddToResultKeys(n.Pinning.RecursiveKeys(), "recursive") } res.SetOutput(&RefKeyList{Keys: keys}) From 4244f71dcd48e7f82f5a9e1fee19f7f3c6e41627 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 12 Jan 2016 22:36:52 +0100 Subject: [PATCH 3/8] core/commands/pin: make 'ipfs pin ls' accept path args License: MIT Signed-off-by: Christian Couder --- core/commands/pin.go | 78 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 70 insertions(+), 8 deletions(-) diff --git a/core/commands/pin.go b/core/commands/pin.go index 9b595e38158..11bffe8afdc 100644 --- a/core/commands/pin.go +++ b/core/commands/pin.go @@ -7,8 +7,11 @@ import ( key "github.com/ipfs/go-ipfs/blocks/key" cmds "github.com/ipfs/go-ipfs/commands" + context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context" + core "github.com/ipfs/go-ipfs/core" corerepo "github.com/ipfs/go-ipfs/core/corerepo" dag "github.com/ipfs/go-ipfs/merkledag" + path "github.com/ipfs/go-ipfs/path" u "github.com/ipfs/go-ipfs/util" ) @@ -183,6 +186,9 @@ Example: `, }, + Arguments: []cmds.Argument{ + cmds.StringArg("ipfs-path", false, true, "Path to object(s) to be listed"), + }, Options: []cmds.Option{ cmds.StringOption("type", "t", "The type of pinned keys to list. Can be \"direct\", \"indirect\", \"recursive\", or \"all\". Defaults to \"recursive\""), cmds.BoolOption("count", "n", "Show refcount when listing indirect pins"), @@ -195,20 +201,40 @@ Example: return } - typeStr, found, err := req.Option("type").String() + typeStr, typeStrFound, err := req.Option("type").String() if err != nil { res.SetError(err, cmds.ErrNormal) return } - if !found { - typeStr = "recursive" + + if typeStrFound { + switch typeStr { + case "all", "direct", "indirect", "recursive": + default: + err = fmt.Errorf("Invalid type '%s', must be one of {direct, indirect, recursive, all}", typeStr) + res.SetError(err, cmds.ErrClient) + return + } } - switch typeStr { - case "all", "direct", "indirect", "recursive": - default: - err = fmt.Errorf("Invalid type '%s', must be one of {direct, indirect, recursive, all}", typeStr) - res.SetError(err, cmds.ErrClient) + if len(req.Arguments()) > 0 { + if !typeStrFound { + typeStr = "all" + } + + keys, err := pinLsKeys(req.Arguments(), typeStr, req.Context(), n) + + if err != nil { + res.SetError(err, cmds.ErrNormal) + } else { + res.SetOutput(&RefKeyList{Keys: keys}) + } + + return + } + + if !typeStrFound { + typeStr = "recursive" } keys := make(map[string]RefKeyObject) @@ -278,3 +304,39 @@ type RefKeyObject struct { type RefKeyList struct { Keys map[string]RefKeyObject } + +func pinLsKeys(args []string, typeStr string, ctx context.Context, n *core.IpfsNode) (map[string]RefKeyObject, error) { + keys := make(map[string]RefKeyObject) + + for _, p := range args { + dagNode, err := core.Resolve(ctx, n, path.Path(p)) + if err != nil { + return nil, err + } + + k, err := dagNode.Key() + if err != nil { + return nil, err + } + + pinType, pinned, err := n.Pinning.IsPinnedWithType(k, typeStr) + if err != nil { + return nil, err + } + + if !pinned { + return nil, fmt.Errorf("Path '%s' is not pinned", p) + } + + switch pinType { + case "direct", "indirect", "recursive", "internal": + default: + pinType = "indirect through " + pinType + } + keys[k.B58String()] = RefKeyObject{ + Type: pinType, + } + } + + return keys, nil +} From d87ece14ceee5aee3488a4ee17c1c0e640ece996 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sun, 17 Jan 2016 22:01:20 +0100 Subject: [PATCH 4/8] core/commands/pin: refactor listing all pins License: MIT Signed-off-by: Christian Couder --- core/commands/pin.go | 92 +++++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/core/commands/pin.go b/core/commands/pin.go index 11bffe8afdc..ae3abc522f7 100644 --- a/core/commands/pin.go +++ b/core/commands/pin.go @@ -217,60 +217,27 @@ Example: } } + var keys map[string]RefKeyObject + if len(req.Arguments()) > 0 { if !typeStrFound { typeStr = "all" } - keys, err := pinLsKeys(req.Arguments(), typeStr, req.Context(), n) - - if err != nil { - res.SetError(err, cmds.ErrNormal) - } else { - res.SetOutput(&RefKeyList{Keys: keys}) + keys, err = pinLsKeys(req.Arguments(), typeStr, req.Context(), n) + } else { + if !typeStrFound { + typeStr = "recursive" } - return - } - - if !typeStrFound { - typeStr = "recursive" - } - - keys := make(map[string]RefKeyObject) - - AddToResultKeys := func(keyList []key.Key, typeStr string) { - for _, k := range keyList { - keys[k.B58String()] = RefKeyObject{ - Type: typeStr, - } - } + keys, err = pinLsAll(typeStr, req.Context(), n) } - if typeStr == "direct" || typeStr == "all" { - AddToResultKeys(n.Pinning.DirectKeys(), "direct") - } - if typeStr == "indirect" || typeStr == "all" { - ks := key.NewKeySet() - for _, k := range n.Pinning.RecursiveKeys() { - nd, err := n.DAG.Get(n.Context(), k) - if err != nil { - res.SetError(err, cmds.ErrNormal) - return - } - err = dag.EnumerateChildren(n.Context(), n.DAG, nd, ks) - if err != nil { - res.SetError(err, cmds.ErrNormal) - return - } - } - AddToResultKeys(ks.Keys(), "indirect") - } - if typeStr == "recursive" || typeStr == "all" { - AddToResultKeys(n.Pinning.RecursiveKeys(), "recursive") + if err != nil { + res.SetError(err, cmds.ErrNormal) + } else { + res.SetOutput(&RefKeyList{Keys: keys}) } - - res.SetOutput(&RefKeyList{Keys: keys}) }, Type: RefKeyList{}, Marshalers: cmds.MarshalerMap{ @@ -306,6 +273,7 @@ type RefKeyList struct { } func pinLsKeys(args []string, typeStr string, ctx context.Context, n *core.IpfsNode) (map[string]RefKeyObject, error) { + keys := make(map[string]RefKeyObject) for _, p := range args { @@ -340,3 +308,39 @@ func pinLsKeys(args []string, typeStr string, ctx context.Context, n *core.IpfsN return keys, nil } + +func pinLsAll(typeStr string, ctx context.Context, n *core.IpfsNode) (map[string]RefKeyObject, error) { + + keys := make(map[string]RefKeyObject) + + AddToResultKeys := func(keyList []key.Key, typeStr string) { + for _, k := range keyList { + keys[k.B58String()] = RefKeyObject{ + Type: typeStr, + } + } + } + + if typeStr == "direct" || typeStr == "all" { + AddToResultKeys(n.Pinning.DirectKeys(), "direct") + } + if typeStr == "indirect" || typeStr == "all" { + ks := key.NewKeySet() + for _, k := range n.Pinning.RecursiveKeys() { + nd, err := n.DAG.Get(ctx, k) + if err != nil { + return nil, err + } + err = dag.EnumerateChildren(n.Context(), n.DAG, nd, ks) + if err != nil { + return nil, err + } + } + AddToResultKeys(ks.Keys(), "indirect") + } + if typeStr == "recursive" || typeStr == "all" { + AddToResultKeys(n.Pinning.RecursiveKeys(), "recursive") + } + + return keys, nil +} From f5f923a7a893ba5ca12a05cdd00c48c6c648a275 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sat, 16 Jan 2016 16:59:07 +0100 Subject: [PATCH 5/8] core/commands/pin: update 'ipfs pin ls' documentation License: MIT Signed-off-by: Christian Couder --- core/commands/pin.go | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/core/commands/pin.go b/core/commands/pin.go index ae3abc522f7..6b127fea63b 100644 --- a/core/commands/pin.go +++ b/core/commands/pin.go @@ -161,11 +161,11 @@ var listPinCmd = &cmds.Command{ Tagline: "List objects pinned to local storage", ShortDescription: ` Returns a list of objects that are pinned locally. -By default, only recursively pinned returned, but others may be shown via the '--type' flag. +Without arguments, by default, only recursively pinned objects are returned, but others may be shown via the '--type' flag. `, LongDescription: ` Returns a list of objects that are pinned locally. -By default, only recursively pinned returned, but others may be shown via the '--type' flag. +Without arguments, by default, only recursively pinned objects are returned, but others may be shown via the '--type' flag. Use --type= to specify the type of pinned keys to list. Valid values are: * "direct": pin that specific object. @@ -173,16 +173,23 @@ Use --type= to specify the type of pinned keys to list. Valid values are: * "indirect": pinned indirectly by an ancestor (like a refcount) * "all" +With arguments, the command fails if any of the arguments is not a pinned object. +And if --type= is additionally used, the command will also fail if any of the arguments is not of the specified type. + Example: $ echo "hello" | ipfs add -q QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN $ ipfs pin ls - QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN + QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN recursive # now remove the pin, and repin it directly $ ipfs pin rm QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN + unpinned QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN $ ipfs pin add -r=false QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN + pinned QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN directly $ ipfs pin ls --type=direct - QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN + QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN direct + $ ipfs pin ls QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN + QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN direct `, }, From 893ab6dc8333719027f2704712d6886f11aecb22 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sat, 16 Jan 2016 13:12:10 +0100 Subject: [PATCH 6/8] t0081: use 'ipfs pin ls ' in test_pin_flagi() License: MIT Signed-off-by: Christian Couder --- test/sharness/t0081-repo-pinning.sh | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/test/sharness/t0081-repo-pinning.sh b/test/sharness/t0081-repo-pinning.sh index 8b0d2bcdb05..b3bc1138da2 100755 --- a/test/sharness/t0081-repo-pinning.sh +++ b/test/sharness/t0081-repo-pinning.sh @@ -8,30 +8,23 @@ test_description="Test ipfs repo pinning" . lib/test-lib.sh - - test_pin_flag() { object=$1 ptype=$2 expect=$3 - echo "test_pin_flag" $@ + echo "test_pin_flag" "$@" - ipfs-pin-stat "$object" | egrep "\b$ptype\b" - actual=$? - - if [ "$expect" = "true" ]; then - if [ "$actual" != "0" ]; then - echo "$object should be pinned $ptype ($actual)" - return 1 - fi + if ipfs pin ls --type="$ptype" "$object" >actual + then + test "$expect" = "true" && return + test_fsh cat actual + return else - if [ "$actual" != "1" ]; then - echo "$object should NOT be pinned $ptype ($actual)" - return 1 - fi + test "$expect" = "false" && return + test_fsh cat actual + return fi - return 0 } test_pin() { From 2dd4f40c1050871d4957c1f9a5d48218d8348aac Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sat, 16 Jan 2016 16:12:58 +0100 Subject: [PATCH 7/8] test/bin: remove ipfs-pin-stat License: MIT Signed-off-by: Christian Couder --- test/bin/.gitignore | 1 - test/bin/ipfs-pin-stat | 30 ------------------------------ 2 files changed, 31 deletions(-) delete mode 100755 test/bin/ipfs-pin-stat diff --git a/test/bin/.gitignore b/test/bin/.gitignore index ad9f6010df8..c032badeef4 100644 --- a/test/bin/.gitignore +++ b/test/bin/.gitignore @@ -7,5 +7,4 @@ # Do not ignore the following special scripts !checkflags !continueyn -!ipfs-pin-stat !verify-go-fmt.sh diff --git a/test/bin/ipfs-pin-stat b/test/bin/ipfs-pin-stat deleted file mode 100755 index 967ee9b653a..00000000000 --- a/test/bin/ipfs-pin-stat +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh - -die() { - echo "$@" - exit 1 -} - -if [ "$#" -eq 0 ]; then - echo "usage: $0 " - echo "show ipfs pin information for object" - exit 1 -fi - -path=$1 - -echo "$path" | grep "/" >/dev/null -if [ "$?" -eq 0 ]; then - die "error: paths not supported. please resolve to hash first." -fi - -ipfs pin ls --type=recursive | grep "$path" >/dev/null -[ "$?" -eq 0 ] && echo "$path pinned recursive-ly" - -ipfs pin ls --type=indirect | grep "$path" >/dev/null -[ "$?" -eq 0 ] && echo "$path pinned indirect-ly" - -ipfs pin ls --type=direct | grep "$path" >/dev/null -[ "$?" -eq 0 ] && echo "$path pinned direct-ly" - -exit 0 From 29830da6a532a5264469c2091b89b531cc771bd6 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Wed, 20 Jan 2016 21:20:36 +0100 Subject: [PATCH 8/8] core/commands/pin: change the default for --type to 'all' License: MIT Signed-off-by: Christian Couder --- CHANGELOG.md | 9 +++++++++ core/commands/pin.go | 14 ++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b592b58b311..362a6bdba67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # go-ipfs changelog +### 0.4.0 - 2016-01-31 + +* Features + * add optional path arguments to 'ipfs pin ls' (@chriscool) + +* Incompatible Changes + * the default for '--type' in 'ipfs pin ls' is now "all" (@chriscool) + + ### 0.3.10 - 2015-12-07 This patch update introduces the 'ipfs update' command which will be used for diff --git a/core/commands/pin.go b/core/commands/pin.go index 6b127fea63b..4a43275e47e 100644 --- a/core/commands/pin.go +++ b/core/commands/pin.go @@ -161,11 +161,11 @@ var listPinCmd = &cmds.Command{ Tagline: "List objects pinned to local storage", ShortDescription: ` Returns a list of objects that are pinned locally. -Without arguments, by default, only recursively pinned objects are returned, but others may be shown via the '--type' flag. +By default, all pinned objects are returned, but the '--type' flag or arguments can restrict that to a specific pin type or to some specific objects respectively. `, LongDescription: ` Returns a list of objects that are pinned locally. -Without arguments, by default, only recursively pinned objects are returned, but others may be shown via the '--type' flag. +By default, all pinned objects are returned, but the '--type' flag or arguments can restrict that to a specific pin type or to some specific objects respectively. Use --type= to specify the type of pinned keys to list. Valid values are: * "direct": pin that specific object. @@ -222,21 +222,15 @@ Example: res.SetError(err, cmds.ErrClient) return } + } else { + typeStr = "all" } var keys map[string]RefKeyObject if len(req.Arguments()) > 0 { - if !typeStrFound { - typeStr = "all" - } - keys, err = pinLsKeys(req.Arguments(), typeStr, req.Context(), n) } else { - if !typeStrFound { - typeStr = "recursive" - } - keys, err = pinLsAll(typeStr, req.Context(), n) }