mirror of
https://github.com/ipfs/kubo.git
synced 2026-02-21 10:27:46 +08:00
Merge pull request ipfs/boxoipfs/interface-go-ipfs-core#50 from MichaelMure/pinispinned
add Pin.IsPinned(..) This commit was moved from ipfs/interface-go-ipfs-core@ee0d435cd1 This commit was moved from ipfs/boxo@150e1b6bea
This commit is contained in:
commit
1babbda938
@ -1,31 +1,49 @@
|
||||
package options
|
||||
|
||||
import "fmt"
|
||||
|
||||
// PinAddSettings represent the settings for PinAPI.Add
|
||||
type PinAddSettings struct {
|
||||
Recursive bool
|
||||
}
|
||||
|
||||
// PinLsSettings represent the settings for PinAPI.Ls
|
||||
type PinLsSettings struct {
|
||||
Type string
|
||||
}
|
||||
|
||||
// PinRmSettings represents the settings of pin rm command
|
||||
// PinIsPinnedSettings represent the settings for PinAPI.IsPinned
|
||||
type PinIsPinnedSettings struct {
|
||||
WithType string
|
||||
}
|
||||
|
||||
// PinRmSettings represents the settings for PinAPI.Rm
|
||||
type PinRmSettings struct {
|
||||
Recursive bool
|
||||
}
|
||||
|
||||
// PinUpdateSettings represent the settings for PinAPI.Update
|
||||
type PinUpdateSettings struct {
|
||||
Unpin bool
|
||||
}
|
||||
|
||||
// PinAddOption is the signature of an option for PinAPI.Add
|
||||
type PinAddOption func(*PinAddSettings) error
|
||||
|
||||
// PinRmOption pin rm option func
|
||||
// PinLsOption is the signature of an option for PinAPI.Ls
|
||||
type PinLsOption func(*PinLsSettings) error
|
||||
|
||||
// PinIsPinnedOption is the signature of an option for PinAPI.IsPinned
|
||||
type PinIsPinnedOption func(*PinIsPinnedSettings) error
|
||||
|
||||
// PinRmOption is the signature of an option for PinAPI.Rm
|
||||
type PinRmOption func(*PinRmSettings) error
|
||||
|
||||
// PinLsOption pin ls option func
|
||||
type PinLsOption func(*PinLsSettings) error
|
||||
// PinUpdateOption is the signature of an option for PinAPI.Update
|
||||
type PinUpdateOption func(*PinUpdateSettings) error
|
||||
|
||||
// PinAddOptions compile a series of PinAddOption into a ready to use
|
||||
// PinAddSettings and set the default values.
|
||||
func PinAddOptions(opts ...PinAddOption) (*PinAddSettings, error) {
|
||||
options := &PinAddSettings{
|
||||
Recursive: true,
|
||||
@ -41,21 +59,8 @@ func PinAddOptions(opts ...PinAddOption) (*PinAddSettings, error) {
|
||||
return options, nil
|
||||
}
|
||||
|
||||
// PinRmOptions pin rm options
|
||||
func PinRmOptions(opts ...PinRmOption) (*PinRmSettings, error) {
|
||||
options := &PinRmSettings{
|
||||
Recursive: true,
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
if err := opt(options); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return options, nil
|
||||
}
|
||||
|
||||
// PinLsOptions compile a series of PinLsOption into a ready to use
|
||||
// PinLsSettings and set the default values.
|
||||
func PinLsOptions(opts ...PinLsOption) (*PinLsSettings, error) {
|
||||
options := &PinLsSettings{
|
||||
Type: "all",
|
||||
@ -71,6 +76,41 @@ func PinLsOptions(opts ...PinLsOption) (*PinLsSettings, error) {
|
||||
return options, nil
|
||||
}
|
||||
|
||||
// PinIsPinnedOptions compile a series of PinIsPinnedOption into a ready to use
|
||||
// PinIsPinnedSettings and set the default values.
|
||||
func PinIsPinnedOptions(opts ...PinIsPinnedOption) (*PinIsPinnedSettings, error) {
|
||||
options := &PinIsPinnedSettings{
|
||||
WithType: "all",
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
err := opt(options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return options, nil
|
||||
}
|
||||
|
||||
// PinRmOptions compile a series of PinRmOption into a ready to use
|
||||
// PinRmSettings and set the default values.
|
||||
func PinRmOptions(opts ...PinRmOption) (*PinRmSettings, error) {
|
||||
options := &PinRmSettings{
|
||||
Recursive: true,
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
if err := opt(options); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return options, nil
|
||||
}
|
||||
|
||||
// PinUpdateOptions compile a series of PinUpdateOption into a ready to use
|
||||
// PinUpdateSettings and set the default values.
|
||||
func PinUpdateOptions(opts ...PinUpdateOption) (*PinUpdateSettings, error) {
|
||||
options := &PinUpdateSettings{
|
||||
Unpin: true,
|
||||
@ -86,36 +126,132 @@ func PinUpdateOptions(opts ...PinUpdateOption) (*PinUpdateSettings, error) {
|
||||
return options, nil
|
||||
}
|
||||
|
||||
type pinType struct{}
|
||||
|
||||
type pinOpts struct {
|
||||
Type pinType
|
||||
Ls pinLsOpts
|
||||
IsPinned pinIsPinnedOpts
|
||||
}
|
||||
|
||||
// Pin provide an access to all the options for the Pin API.
|
||||
var Pin pinOpts
|
||||
|
||||
type pinLsOpts struct{}
|
||||
|
||||
// All is an option for Pin.Ls which will make it return all pins. It is
|
||||
// the default
|
||||
func (pinType) All() PinLsOption {
|
||||
return Pin.pinType("all")
|
||||
func (pinLsOpts) All() PinLsOption {
|
||||
return Pin.Ls.pinType("all")
|
||||
}
|
||||
|
||||
// Recursive is an option for Pin.Ls which will make it only return recursive
|
||||
// pins
|
||||
func (pinType) Recursive() PinLsOption {
|
||||
return Pin.pinType("recursive")
|
||||
func (pinLsOpts) Recursive() PinLsOption {
|
||||
return Pin.Ls.pinType("recursive")
|
||||
}
|
||||
|
||||
// Direct is an option for Pin.Ls which will make it only return direct (non
|
||||
// recursive) pins
|
||||
func (pinType) Direct() PinLsOption {
|
||||
return Pin.pinType("direct")
|
||||
func (pinLsOpts) Direct() PinLsOption {
|
||||
return Pin.Ls.pinType("direct")
|
||||
}
|
||||
|
||||
// Indirect is an option for Pin.Ls which will make it only return indirect pins
|
||||
// (objects referenced by other recursively pinned objects)
|
||||
func (pinType) Indirect() PinLsOption {
|
||||
return Pin.pinType("indirect")
|
||||
func (pinLsOpts) Indirect() PinLsOption {
|
||||
return Pin.Ls.pinType("indirect")
|
||||
}
|
||||
|
||||
// Type is an option for Pin.Ls which will make it only return pins of the given
|
||||
// type.
|
||||
//
|
||||
// Supported values:
|
||||
// * "direct" - directly pinned objects
|
||||
// * "recursive" - roots of recursive pins
|
||||
// * "indirect" - indirectly pinned objects (referenced by recursively pinned
|
||||
// objects)
|
||||
// * "all" - all pinned objects (default)
|
||||
func (pinLsOpts) Type(typeStr string) (PinLsOption, error) {
|
||||
switch typeStr {
|
||||
case "all", "direct", "indirect", "recursive":
|
||||
return Pin.Ls.pinType(typeStr), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid type '%s', must be one of {direct, indirect, recursive, all}", typeStr)
|
||||
}
|
||||
}
|
||||
|
||||
// pinType is an option for Pin.Ls which allows to specify which pin types should
|
||||
// be returned
|
||||
//
|
||||
// Supported values:
|
||||
// * "direct" - directly pinned objects
|
||||
// * "recursive" - roots of recursive pins
|
||||
// * "indirect" - indirectly pinned objects (referenced by recursively pinned
|
||||
// objects)
|
||||
// * "all" - all pinned objects (default)
|
||||
func (pinLsOpts) pinType(t string) PinLsOption {
|
||||
return func(settings *PinLsSettings) error {
|
||||
settings.Type = t
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
type pinIsPinnedOpts struct{}
|
||||
|
||||
// All is an option for Pin.IsPinned which will make it search in all type of pins.
|
||||
// It is the default
|
||||
func (pinIsPinnedOpts) All() PinIsPinnedOption {
|
||||
return Pin.IsPinned.pinType("all")
|
||||
}
|
||||
|
||||
// Recursive is an option for Pin.IsPinned which will make it only search in
|
||||
// recursive pins
|
||||
func (pinIsPinnedOpts) Recursive() PinIsPinnedOption {
|
||||
return Pin.IsPinned.pinType("recursive")
|
||||
}
|
||||
|
||||
// Direct is an option for Pin.IsPinned which will make it only search in direct
|
||||
// (non recursive) pins
|
||||
func (pinIsPinnedOpts) Direct() PinIsPinnedOption {
|
||||
return Pin.IsPinned.pinType("direct")
|
||||
}
|
||||
|
||||
// Indirect is an option for Pin.IsPinned which will make it only search indirect
|
||||
// pins (objects referenced by other recursively pinned objects)
|
||||
func (pinIsPinnedOpts) Indirect() PinIsPinnedOption {
|
||||
return Pin.IsPinned.pinType("indirect")
|
||||
}
|
||||
|
||||
// Type is an option for Pin.IsPinned which will make it only search pins of the given
|
||||
// type.
|
||||
//
|
||||
// Supported values:
|
||||
// * "direct" - directly pinned objects
|
||||
// * "recursive" - roots of recursive pins
|
||||
// * "indirect" - indirectly pinned objects (referenced by recursively pinned
|
||||
// objects)
|
||||
// * "all" - all pinned objects (default)
|
||||
func (pinIsPinnedOpts) Type(typeStr string) (PinIsPinnedOption, error) {
|
||||
switch typeStr {
|
||||
case "all", "direct", "indirect", "recursive":
|
||||
return Pin.IsPinned.pinType(typeStr), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid type '%s', must be one of {direct, indirect, recursive, all}", typeStr)
|
||||
}
|
||||
}
|
||||
|
||||
// pinType is an option for Pin.IsPinned which allows to specify which pin type the given
|
||||
// pin is expected to be, speeding up the research.
|
||||
//
|
||||
// Supported values:
|
||||
// * "direct" - directly pinned objects
|
||||
// * "recursive" - roots of recursive pins
|
||||
// * "indirect" - indirectly pinned objects (referenced by recursively pinned
|
||||
// objects)
|
||||
// * "all" - all pinned objects (default)
|
||||
func (pinIsPinnedOpts) pinType(t string) PinIsPinnedOption {
|
||||
return func(settings *PinIsPinnedSettings) error {
|
||||
settings.WithType = t
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Recursive is an option for Pin.Add which specifies whether to pin an entire
|
||||
@ -137,22 +273,6 @@ func (pinOpts) RmRecursive(recursive bool) PinRmOption {
|
||||
}
|
||||
}
|
||||
|
||||
// Type is an option for Pin.Ls which allows to specify which pin types should
|
||||
// be returned
|
||||
//
|
||||
// Supported values:
|
||||
// * "direct" - directly pinned objects
|
||||
// * "recursive" - roots of recursive pins
|
||||
// * "indirect" - indirectly pinned objects (referenced by recursively pinned
|
||||
// objects)
|
||||
// * "all" - all pinned objects (default)
|
||||
func (pinOpts) pinType(t string) PinLsOption {
|
||||
return func(settings *PinLsSettings) error {
|
||||
settings.Type = t
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Unpin is an option for Pin.Update which specifies whether to remove the old pin.
|
||||
// Default is true.
|
||||
func (pinOpts) Unpin(unpin bool) PinUpdateOption {
|
||||
|
||||
@ -46,6 +46,10 @@ type PinAPI interface {
|
||||
// Ls returns list of pinned objects on this node
|
||||
Ls(context.Context, ...options.PinLsOption) (<-chan Pin, error)
|
||||
|
||||
// IsPinned returns whether or not the given cid is pinned
|
||||
// and an explanation of why its pinned
|
||||
IsPinned(context.Context, path.Path, ...options.PinIsPinnedOption) (string, bool, error)
|
||||
|
||||
// Rm removes pin for object specified by the path
|
||||
Rm(context.Context, path.Path, ...options.PinRmOption) error
|
||||
|
||||
|
||||
@ -28,6 +28,7 @@ func (tp *TestSuite) TestPin(t *testing.T) {
|
||||
t.Run("TestPinRecursive", tp.TestPinRecursive)
|
||||
t.Run("TestPinLsIndirect", tp.TestPinLsIndirect)
|
||||
t.Run("TestPinLsPrecedence", tp.TestPinLsPrecedence)
|
||||
t.Run("TestPinIsPinned", tp.TestPinIsPinned)
|
||||
}
|
||||
|
||||
func (tp *TestSuite) TestPinAdd(t *testing.T) {
|
||||
@ -84,6 +85,8 @@ func (tp *TestSuite) TestPinSimple(t *testing.T) {
|
||||
t.Error("unexpected pin type")
|
||||
}
|
||||
|
||||
assertIsPinned(t, ctx, api, p, "recursive")
|
||||
|
||||
err = api.Pin().Rm(ctx, p)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -150,7 +153,7 @@ func (tp *TestSuite) TestPinRecursive(t *testing.T) {
|
||||
t.Errorf("unexpected pin list len: %d", len(list))
|
||||
}
|
||||
|
||||
list, err = accPins(api.Pin().Ls(ctx, opt.Pin.Type.Direct()))
|
||||
list, err = accPins(api.Pin().Ls(ctx, opt.Pin.Ls.Direct()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -163,7 +166,7 @@ func (tp *TestSuite) TestPinRecursive(t *testing.T) {
|
||||
t.Errorf("unexpected path, %s != %s", list[0].Path().String(), path.IpfsPath(nd3.Cid()).String())
|
||||
}
|
||||
|
||||
list, err = accPins(api.Pin().Ls(ctx, opt.Pin.Type.Recursive()))
|
||||
list, err = accPins(api.Pin().Ls(ctx, opt.Pin.Ls.Recursive()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -176,7 +179,7 @@ func (tp *TestSuite) TestPinRecursive(t *testing.T) {
|
||||
t.Errorf("unexpected path, %s != %s", list[0].Path().String(), path.IpldPath(nd2.Cid()).String())
|
||||
}
|
||||
|
||||
list, err = accPins(api.Pin().Ls(ctx, opt.Pin.Type.Indirect()))
|
||||
list, err = accPins(api.Pin().Ls(ctx, opt.Pin.Ls.Indirect()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -360,6 +363,39 @@ func (tp *TestSuite) TestPinLsPrecedenceRecursiveDirect(t *testing.T) {
|
||||
assertPinTypes(t, ctx, api, []cidContainer{grandparent, parent}, []cidContainer{}, []cidContainer{leaf})
|
||||
}
|
||||
|
||||
func (tp *TestSuite) TestPinIsPinned(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
api, err := tp.makeAPI(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
leaf, parent, grandparent := getThreeChainedNodes(t, ctx, api, "foofoo")
|
||||
|
||||
assertNotPinned(t, ctx, api, path.IpldPath(grandparent.Cid()))
|
||||
assertNotPinned(t, ctx, api, path.IpldPath(parent.Cid()))
|
||||
assertNotPinned(t, ctx, api, path.IpldPath(leaf.Cid()))
|
||||
|
||||
err = api.Pin().Add(ctx, path.IpldPath(parent.Cid()), opt.Pin.Recursive(true))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assertNotPinned(t, ctx, api, path.IpldPath(grandparent.Cid()))
|
||||
assertIsPinned(t, ctx, api, path.IpldPath(parent.Cid()), "recursive")
|
||||
assertIsPinned(t, ctx, api, path.IpldPath(leaf.Cid()), "indirect")
|
||||
|
||||
err = api.Pin().Add(ctx, path.IpldPath(grandparent.Cid()), opt.Pin.Recursive(false))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assertIsPinned(t, ctx, api, path.IpldPath(grandparent.Cid()), "direct")
|
||||
assertIsPinned(t, ctx, api, path.IpldPath(parent.Cid()), "recursive")
|
||||
assertIsPinned(t, ctx, api, path.IpldPath(leaf.Cid()), "indirect")
|
||||
}
|
||||
|
||||
type cidContainer interface {
|
||||
Cid() cid.Cid
|
||||
}
|
||||
@ -390,21 +426,21 @@ func getThreeChainedNodes(t *testing.T, ctx context.Context, api iface.CoreAPI,
|
||||
func assertPinTypes(t *testing.T, ctx context.Context, api iface.CoreAPI, recusive, direct, indirect []cidContainer) {
|
||||
assertPinLsAllConsistency(t, ctx, api)
|
||||
|
||||
list, err := accPins(api.Pin().Ls(ctx, opt.Pin.Type.Recursive()))
|
||||
list, err := accPins(api.Pin().Ls(ctx, opt.Pin.Ls.Recursive()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assertPinCids(t, list, recusive...)
|
||||
|
||||
list, err = accPins(api.Pin().Ls(ctx, opt.Pin.Type.Direct()))
|
||||
list, err = accPins(api.Pin().Ls(ctx, opt.Pin.Ls.Direct()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assertPinCids(t, list, direct...)
|
||||
|
||||
list, err = accPins(api.Pin().Ls(ctx, opt.Pin.Type.Indirect()))
|
||||
list, err = accPins(api.Pin().Ls(ctx, opt.Pin.Ls.Indirect()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -466,9 +502,9 @@ func assertPinLsAllConsistency(t *testing.T, ctx context.Context, api iface.Core
|
||||
|
||||
all, recursive, direct, indirect := cid.NewSet(), cid.NewSet(), cid.NewSet(), cid.NewSet()
|
||||
typeMap := map[string]*pinTypeProps{
|
||||
"recursive": {recursive, opt.Pin.Type.Recursive()},
|
||||
"direct": {direct, opt.Pin.Type.Direct()},
|
||||
"indirect": {indirect, opt.Pin.Type.Indirect()},
|
||||
"recursive": {recursive, opt.Pin.Ls.Recursive()},
|
||||
"direct": {direct, opt.Pin.Ls.Direct()},
|
||||
"indirect": {indirect, opt.Pin.Ls.Indirect()},
|
||||
}
|
||||
|
||||
for _, p := range allPins {
|
||||
@ -506,6 +542,47 @@ func assertPinLsAllConsistency(t *testing.T, ctx context.Context, api iface.Core
|
||||
}
|
||||
}
|
||||
|
||||
func assertIsPinned(t *testing.T, ctx context.Context, api iface.CoreAPI, p path.Path, typeStr string) {
|
||||
t.Helper()
|
||||
withType, err := opt.Pin.IsPinned.Type(typeStr)
|
||||
if err != nil {
|
||||
t.Fatal("unhandled pin type")
|
||||
}
|
||||
|
||||
whyPinned, pinned, err := api.Pin().IsPinned(ctx, p, withType)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !pinned {
|
||||
t.Fatalf("%s expected to be pinned with type %s", p, typeStr)
|
||||
}
|
||||
|
||||
switch typeStr {
|
||||
case "recursive", "direct":
|
||||
if typeStr != whyPinned {
|
||||
t.Fatalf("reason for pinning expected to be %s for %s, got %s", typeStr, p, whyPinned)
|
||||
}
|
||||
case "indirect":
|
||||
if whyPinned == "" {
|
||||
t.Fatalf("expected to have a pin reason for %s", p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func assertNotPinned(t *testing.T, ctx context.Context, api iface.CoreAPI, p path.Path) {
|
||||
t.Helper()
|
||||
|
||||
_, pinned, err := api.Pin().IsPinned(ctx, p)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if pinned {
|
||||
t.Fatalf("%s expected to not be pinned", p)
|
||||
}
|
||||
}
|
||||
|
||||
func accPins(pins <-chan iface.Pin, err error) ([]iface.Pin, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
Loading…
Reference in New Issue
Block a user