Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make pin rm not try to find pinned ancestors by default #3600

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion core/commands/pin.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ collected if needed. (By default, recursively. Use -r=false for direct pins.)
},
Options: []cmdkit.Option{
cmdkit.BoolOption("recursive", "r", "Recursively unpin the object linked to by the specified object(s).").WithDefault(true),
cmdkit.BoolOption("explain", "e", "Check for other pinned objects which could cause specified object(s) to be indirectly pinned").WithDefault(false),
},
Type: PinOutput{},
Run: func(req cmds.Request, res cmds.Response) {
Expand All @@ -200,7 +201,13 @@ collected if needed. (By default, recursively. Use -r=false for direct pins.)
return
}

removed, err := corerepo.Unpin(n, req.Context(), req.Arguments(), recursive)
explain, _, err := req.Option("explain").Bool()
if err != nil {
res.SetError(err, cmdkit.ErrNormal)
return
}

removed, err := corerepo.Unpin(n, req.Context(), req.Arguments(), recursive, explain)
if err != nil {
res.SetError(err, cmdkit.ErrNormal)
return
Expand Down
2 changes: 1 addition & 1 deletion core/coreapi/pin.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func (api *PinAPI) Ls(ctx context.Context, opts ...caopts.PinLsOption) ([]coreif
}

func (api *PinAPI) Rm(ctx context.Context, p coreiface.Path) error {
_, err := corerepo.Unpin(api.node, ctx, []string{p.String()}, true)
_, err := corerepo.Unpin(api.node, ctx, []string{p.String()}, true, true)
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions core/corerepo/pinning.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func Pin(n *core.IpfsNode, ctx context.Context, paths []string, recursive bool)
return out, nil
}

func Unpin(n *core.IpfsNode, ctx context.Context, paths []string, recursive bool) ([]*cid.Cid, error) {
func Unpin(n *core.IpfsNode, ctx context.Context, paths []string, recursive bool, explain bool) ([]*cid.Cid, error) {
unpinned := make([]*cid.Cid, len(paths))

r := &resolver.Resolver{
Expand All @@ -77,7 +77,7 @@ func Unpin(n *core.IpfsNode, ctx context.Context, paths []string, recursive bool
return nil, err
}

err = n.Pinning.Unpin(ctx, k, recursive)
err = n.Pinning.Unpin(ctx, k, recursive, explain)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion core/coreunix/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ func (adder *Adder) PinRoot() error {
}

if adder.tempRoot != nil {
err := adder.pinning.Unpin(adder.ctx, adder.tempRoot, true)
err := adder.pinning.Unpin(adder.ctx, adder.tempRoot, true, false)
if err != nil {
return err
}
Expand Down
58 changes: 44 additions & 14 deletions pin/pin.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ type Pinner interface {

// Unpin the given cid. If recursive is true, removes either a recursive or
// a direct pin. If recursive is false, only removes a direct pin.
Unpin(ctx context.Context, cid *cid.Cid, recursive bool) error
Unpin(ctx context.Context, cid *cid.Cid, recursive bool, explain bool) error

// Update updates a recursive pin from one cid to another
// this is more efficient than simply pinning the new one and unpinning the
Expand Down Expand Up @@ -254,29 +254,59 @@ func (p *pinner) Pin(ctx context.Context, node ipld.Node, recurse bool) error {
var ErrNotPinned = fmt.Errorf("not pinned")

// Unpin a given key
func (p *pinner) Unpin(ctx context.Context, c *cid.Cid, recursive bool) error {
func (p *pinner) Unpin(ctx context.Context, c *cid.Cid, recursive bool, explain bool) error {
p.lock.Lock()
defer p.lock.Unlock()
reason, pinned, err := p.isPinnedWithType(c, Any)

var pinMode Mode
if recursive {
pinMode = Recursive
} else {
pinMode = Direct
}
_, pinned, err := p.isPinnedWithType(c, pinMode)
if err != nil {
return err
}
if !pinned {
return ErrNotPinned
}
switch reason {
case "recursive":
if pinned {
if recursive {
p.recursePin.Remove(c)
return nil
} else {
p.directPin.Remove(c)
return nil
}
return fmt.Errorf("%s is pinned recursively", c)
case "direct":
p.directPin.Remove(c)
return nil
default:
return fmt.Errorf("%s is pinned indirectly under %s", c, reason)
} else if recursive {
_, pinned, err := p.isPinnedWithType(c, Direct)
if err != nil {
return err
}
if pinned {
p.directPin.Remove(c)
return nil
}
}

if explain {
reason, pinned, err := p.isPinnedWithType(c, Any)
if err != nil {
return err
}
if !pinned {
return ErrNotPinned
}
switch reason {
case "recursive":
return fmt.Errorf("%s is pinned recursively", c)
default:
return fmt.Errorf("%s is pinned indirectly under %s", c, reason)
}
} else if recursive {
return fmt.Errorf("%s is not pinned recursively or directly", c)
} else {
return fmt.Errorf("%s is not pinned directly", c)
}

}

func (p *pinner) isInternalPin(c *cid.Cid) bool {
Expand Down
6 changes: 3 additions & 3 deletions pin/pin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ func TestPinnerBasic(t *testing.T) {
assertPinned(t, p, dk, "pinned node not found.")

// Test recursive unpin
err = p.Unpin(ctx, dk, true)
err = p.Unpin(ctx, dk, true, false)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -261,15 +261,15 @@ func TestIsPinnedLookup(t *testing.T) {
assertPinned(t, p, bk, "B should be pinned")

// Unpin A5 recursively
if err := p.Unpin(ctx, aKeys[5], true); err != nil {
if err := p.Unpin(ctx, aKeys[5], true, false); err != nil {
t.Fatal(err)
}

assertPinned(t, p, aKeys[0], "A0 should still be pinned through B")
assertUnpinned(t, p, aKeys[4], "A4 should be unpinned")

// Unpin B recursively
if err := p.Unpin(ctx, bk, true); err != nil {
if err := p.Unpin(ctx, bk, true, false); err != nil {
t.Fatal(err)
}
assertUnpinned(t, p, bk, "B should be unpinned")
Expand Down
15 changes: 14 additions & 1 deletion test/sharness/t0080-repo.sh
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,17 @@ test_expect_success "pinning directly should fail now" '
'

test_expect_success "'ipfs pin rm -r=false <hash>' should fail" '
echo "Error: $HASH is pinned recursively" >expected4 &&
echo "Error: $HASH is not pinned directly" >expected4 &&
test_must_fail ipfs pin rm -r=false "$HASH" 2>actual4 &&
test_cmp expected4 actual4
'

test_expect_success "'ipfs pin rm -e -r=false <hash>' should fail and explain why" '
echo "Error: $HASH is pinned recursively" >expected11 &&
test_must_fail ipfs pin rm -e -r=false "$HASH" 2>actual11 &&
test_cmp expected11 actual11
'

test_expect_success "remove recursive pin, add direct" '
echo "unpinned $HASH" >expected5 &&
ipfs pin rm -r "$HASH" >actual5 &&
Expand All @@ -100,6 +106,13 @@ test_expect_success "remove recursive pin, add direct" '

test_expect_success "remove direct pin" '
echo "unpinned $HASH" >expected6 &&
ipfs pin rm -r=false "$HASH" >actual6 &&
test_cmp expected6 actual6
'

test_expect_success "remove direct pin with pin rm -r" '
echo "unpinned $HASH" >expected6 &&
ipfs pin add -r=false "$HASH"
ipfs pin rm "$HASH" >actual6 &&
test_cmp expected6 actual6
'
Expand Down
2 changes: 1 addition & 1 deletion test/sharness/t0252-files-gc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ test_expect_success "gc okay after adding incomplete node -- prep" '
ipfs repo gc && # will remove /adir/file1 and /adir/file2 but not /adir
test_must_fail ipfs cat $FILE1_HASH &&
ipfs files cp /ipfs/$ADIR_HASH /adir &&
ipfs pin rm $ADIR_HASH
ipfs pin rm -r=false $ADIR_HASH
'

test_expect_success "gc okay after adding incomplete node" '
Expand Down