Skip to content

Commit

Permalink
feat: support optional pin names (#10261)
Browse files Browse the repository at this point in the history
  • Loading branch information
hacdias authored Jan 4, 2024
1 parent 765cffe commit a8a6bbe
Show file tree
Hide file tree
Showing 22 changed files with 200 additions and 60 deletions.
8 changes: 7 additions & 1 deletion client/rpc/pin.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type pinRefKeyList struct {
type pin struct {
path path.ImmutablePath
typ string
name string
err error
}

Expand All @@ -37,6 +38,10 @@ func (p pin) Path() path.ImmutablePath {
return p.path
}

func (p pin) Name() string {
return p.name
}

func (p pin) Type() string {
return p.typ
}
Expand All @@ -53,6 +58,7 @@ func (api *PinAPI) Add(ctx context.Context, p path.Path, opts ...caopts.PinAddOp

type pinLsObject struct {
Cid string
Name string
Type string
}

Expand Down Expand Up @@ -102,7 +108,7 @@ func (api *PinAPI) Ls(ctx context.Context, opts ...caopts.PinLsOption) (<-chan i
}

select {
case ch <- pin{typ: out.Type, path: path.FromCid(c)}:
case ch <- pin{typ: out.Type, name: out.Name, path: path.FromCid(c)}:
case <-ctx.Done():
return
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/ipfs/kubo/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ func initializeIpnsKeyspace(repoRoot string) error {

// pin recursively because this might already be pinned
// and doing a direct pin would throw an error in that case
err = nd.Pinning.Pin(ctx, emptyDir, true)
err = nd.Pinning.Pin(ctx, emptyDir, true, "")
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion core/commands/dag/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ func dagImport(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment
ret.PinErrorMsg = err.Error()
} else if nd, err := blockDecoder.DecodeNode(req.Context, block); err != nil {
ret.PinErrorMsg = err.Error()
} else if err := node.Pinning.Pin(req.Context, nd, true); err != nil {
} else if err := node.Pinning.Pin(req.Context, nd, true, ""); err != nil {
ret.PinErrorMsg = err.Error()
} else if err := node.Pinning.Flush(req.Context); err != nil {
ret.PinErrorMsg = err.Error()
Expand Down
66 changes: 52 additions & 14 deletions core/commands/pin/pin.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,36 @@ var addPinCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Pin objects to local storage.",
ShortDescription: "Stores an IPFS object(s) from a given path locally to disk.",
LongDescription: `
Create a pin for the given object, protecting resolved CID from being garbage
collected.
An optional name can be provided, and read back via 'ipfs pin ls --names'.
Be mindful of defaults:
Default pin type is 'recursive' (entire DAG).
Pass -r=false to create a direct pin for a single block.
Use 'pin ls -t recursive' to only list roots of recursively pinned DAGs
(significantly faster when many big DAGs are pinned recursively)
Default pin name is empty. Pass '--name' to 'pin add' to set one
and use 'pin ls --names' to see it.
Pin add is idempotent: pinning CID which is already pinned won't change
the name, value passed with '--name' with the original pin is preserved.
To rename pin, use 'pin rm' and 'pin add --name'.
If daemon is running, any missing blocks will be retrieved from the network.
It may take some time. Pass '--progress' to track the progress.
`,
},

Arguments: []cmds.Argument{
cmds.StringArg("ipfs-path", true, true, "Path to object(s) to be pinned.").EnableStdin(),
},
Options: []cmds.Option{
cmds.BoolOption(pinRecursiveOptionName, "r", "Recursively pin the object linked to by the specified object(s).").WithDefault(true),
cmds.StringOption(pinNameOptionName, "n", "An optional name for created pin(s)."),
cmds.BoolOption(pinProgressOptionName, "Show progress"),
},
Type: AddPinOutput{},
Expand All @@ -75,6 +98,7 @@ var addPinCmd = &cmds.Command{

// set recursive flag
recursive, _ := req.Options[pinRecursiveOptionName].(bool)
name, _ := req.Options[pinNameOptionName].(string)
showProgress, _ := req.Options[pinProgressOptionName].(bool)

if err := req.ParseBodyArgs(); err != nil {
Expand All @@ -87,7 +111,7 @@ var addPinCmd = &cmds.Command{
}

if !showProgress {
added, err := pinAddMany(req.Context, api, enc, req.Arguments, recursive)
added, err := pinAddMany(req.Context, api, enc, req.Arguments, recursive, name)
if err != nil {
return err
}
Expand All @@ -105,7 +129,7 @@ var addPinCmd = &cmds.Command{

ch := make(chan pinResult, 1)
go func() {
added, err := pinAddMany(ctx, api, enc, req.Arguments, recursive)
added, err := pinAddMany(ctx, api, enc, req.Arguments, recursive, name)
ch <- pinResult{pins: added, err: err}
}()

Expand Down Expand Up @@ -181,7 +205,7 @@ var addPinCmd = &cmds.Command{
},
}

func pinAddMany(ctx context.Context, api coreiface.CoreAPI, enc cidenc.Encoder, paths []string, recursive bool) ([]string, error) {
func pinAddMany(ctx context.Context, api coreiface.CoreAPI, enc cidenc.Encoder, paths []string, recursive bool, name string) ([]string, error) {
added := make([]string, len(paths))
for i, b := range paths {
p, err := cmdutils.PathOrCidPath(b)
Expand All @@ -194,7 +218,7 @@ func pinAddMany(ctx context.Context, api coreiface.CoreAPI, enc cidenc.Encoder,
return nil, err
}

if err := api.Pin().Add(ctx, rp, options.Pin.Recursive(recursive)); err != nil {
if err := api.Pin().Add(ctx, rp, options.Pin.Recursive(recursive), options.Pin.Name(name)); err != nil {
return nil, err
}
added[i] = enc.Encode(rp.RootCid())
Expand Down Expand Up @@ -281,6 +305,7 @@ const (
pinTypeOptionName = "type"
pinQuietOptionName = "quiet"
pinStreamOptionName = "stream"
pinNamesOptionName = "names"
)

var listPinCmd = &cmds.Command{
Expand All @@ -294,6 +319,7 @@ respectively.
`,
LongDescription: `
Returns a list of objects that are pinned locally.
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.
Expand All @@ -302,10 +328,13 @@ Use --type=<type> to specify the type of pinned keys to list.
Valid values are:
* "direct": pin that specific object.
* "recursive": pin that specific object, and indirectly pin all its
descendants
descendants
* "indirect": pinned indirectly by an ancestor (like a refcount)
* "all"
By default, pin names are not included (returned as empty).
Pass '--names' flag to return pin names (set with '--name' from 'pin add').
With arguments, the command fails if any of the arguments is not a pinned
object. And if --type=<type> is additionally used, the command will also fail
if any of the arguments is not of the specified type.
Expand Down Expand Up @@ -334,6 +363,7 @@ Example:
cmds.StringOption(pinTypeOptionName, "t", "The type of pinned keys to list. Can be \"direct\", \"indirect\", \"recursive\", or \"all\".").WithDefault("all"),
cmds.BoolOption(pinQuietOptionName, "q", "Write just hashes of objects."),
cmds.BoolOption(pinStreamOptionName, "s", "Enable streaming of pins as they are discovered."),
cmds.BoolOption(pinNamesOptionName, "n", "Enable displaying pin names (slower)."),
},
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
api, err := cmdenv.GetApi(env, req)
Expand All @@ -343,6 +373,7 @@ Example:

typeStr, _ := req.Options[pinTypeOptionName].(string)
stream, _ := req.Options[pinStreamOptionName].(bool)
displayNames, _ := req.Options[pinNamesOptionName].(bool)

switch typeStr {
case "all", "direct", "indirect", "recursive":
Expand All @@ -356,7 +387,7 @@ Example:
lgcList := map[string]PinLsType{}
if !stream {
emit = func(v PinLsOutputWrapper) error {
lgcList[v.PinLsObject.Cid] = PinLsType{Type: v.PinLsObject.Type}
lgcList[v.PinLsObject.Cid] = PinLsType{Type: v.PinLsObject.Type, Name: v.PinLsObject.Name}
return nil
}
} else {
Expand All @@ -368,7 +399,7 @@ Example:
if len(req.Arguments) > 0 {
err = pinLsKeys(req, typeStr, api, emit)
} else {
err = pinLsAll(req, typeStr, api, emit)
err = pinLsAll(req, typeStr, displayNames, api, emit)
}
if err != nil {
return err
Expand Down Expand Up @@ -402,17 +433,21 @@ Example:
if stream {
if quiet {
fmt.Fprintf(w, "%s\n", out.PinLsObject.Cid)
} else {
} else if out.PinLsObject.Name == "" {
fmt.Fprintf(w, "%s %s\n", out.PinLsObject.Cid, out.PinLsObject.Type)
} else {
fmt.Fprintf(w, "%s %s %s\n", out.PinLsObject.Cid, out.PinLsObject.Type, out.PinLsObject.Name)
}
return nil
}

for k, v := range out.PinLsList.Keys {
if quiet {
fmt.Fprintf(w, "%s\n", k)
} else {
} else if v.Name == "" {
fmt.Fprintf(w, "%s %s\n", k, v.Type)
} else {
fmt.Fprintf(w, "%s %s %s\n", k, v.Type, v.Name)
}
}

Expand All @@ -437,11 +472,13 @@ type PinLsList struct {
// PinLsType contains the type of a pin
type PinLsType struct {
Type string
Name string
}

// PinLsObject contains the description of a pin
type PinLsObject struct {
Cid string `json:",omitempty"`
Name string `json:",omitempty"`
Type string `json:",omitempty"`
}

Expand Down Expand Up @@ -502,7 +539,7 @@ func pinLsKeys(req *cmds.Request, typeStr string, api coreiface.CoreAPI, emit fu
return nil
}

func pinLsAll(req *cmds.Request, typeStr string, api coreiface.CoreAPI, emit func(value PinLsOutputWrapper) error) error {
func pinLsAll(req *cmds.Request, typeStr string, detailed bool, api coreiface.CoreAPI, emit func(value PinLsOutputWrapper) error) error {
enc, err := cmdenv.GetCidEncoder(req)
if err != nil {
return err
Expand All @@ -520,7 +557,7 @@ func pinLsAll(req *cmds.Request, typeStr string, api coreiface.CoreAPI, emit fun
panic("unhandled pin type")
}

pins, err := api.Pin().Ls(req.Context, opt)
pins, err := api.Pin().Ls(req.Context, opt, options.Pin.Ls.Detailed(detailed))
if err != nil {
return err
}
Expand All @@ -532,6 +569,7 @@ func pinLsAll(req *cmds.Request, typeStr string, api coreiface.CoreAPI, emit fun
err = emit(PinLsOutputWrapper{
PinLsObject: PinLsObject{
Type: p.Type(),
Name: p.Name(),
Cid: enc.Encode(p.Path().RootCid()),
},
})
Expand Down Expand Up @@ -748,15 +786,15 @@ func pinVerify(ctx context.Context, n *core.IpfsNode, opts pinVerifyOpts, enc ci
out := make(chan any)
go func() {
defer close(out)
for p := range n.Pinning.RecursiveKeys(ctx) {
for p := range n.Pinning.RecursiveKeys(ctx, false) {
if p.Err != nil {
out <- PinVerifyRes{Err: p.Err.Error()}
return
}
pinStatus := checkPin(p.C)
pinStatus := checkPin(p.Pin.Key)
if !pinStatus.Ok || opts.includeOk {
select {
case out <- PinVerifyRes{Cid: enc.Encode(p.C), PinStatus: pinStatus}:
case out <- PinVerifyRes{Cid: enc.Encode(p.Pin.Key), PinStatus: pinStatus}:
case <-ctx.Done():
return
}
Expand Down
2 changes: 1 addition & 1 deletion core/coreapi/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func (api *BlockAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.Bloc
}

if settings.Pin {
if err = api.pinning.PinWithMode(ctx, b.Cid(), pin.Recursive); err != nil {
if err = api.pinning.PinWithMode(ctx, b.Cid(), pin.Recursive, ""); err != nil {
return nil, err
}
if err := api.pinning.Flush(ctx); err != nil {
Expand Down
4 changes: 2 additions & 2 deletions core/coreapi/dag.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func (adder *pinningAdder) Add(ctx context.Context, nd ipld.Node) error {
return err
}

if err := adder.pinning.PinWithMode(ctx, nd.Cid(), pin.Recursive); err != nil {
if err := adder.pinning.PinWithMode(ctx, nd.Cid(), pin.Recursive, ""); err != nil {
return err
}

Expand All @@ -51,7 +51,7 @@ func (adder *pinningAdder) AddMany(ctx context.Context, nds []ipld.Node) error {
for _, nd := range nds {
c := nd.Cid()
if cids.Visit(c) {
if err := adder.pinning.PinWithMode(ctx, c, pin.Recursive); err != nil {
if err := adder.pinning.PinWithMode(ctx, c, pin.Recursive, ""); err != nil {
return err
}
}
Expand Down
2 changes: 1 addition & 1 deletion core/coreapi/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ func (api *ObjectAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.Obj
}

if options.Pin {
if err := api.pinning.PinWithMode(ctx, dagnode.Cid(), pin.Recursive); err != nil {
if err := api.pinning.PinWithMode(ctx, dagnode.Cid(), pin.Recursive, ""); err != nil {
return path.ImmutablePath{}, err
}

Expand Down
Loading

0 comments on commit a8a6bbe

Please sign in to comment.