package commands import ( "bytes" "fmt" "io" cmds "github.com/jbenet/go-ipfs/commands" corerepo "github.com/jbenet/go-ipfs/core/repo" u "github.com/jbenet/go-ipfs/util" ) var PinCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Pin (and unpin) objects to local storage", }, Subcommands: map[string]*cmds.Command{ "add": addPinCmd, "rm": rmPinCmd, "ls": listPinCmd, }, } type PinOutput struct { Pinned []u.Key } var addPinCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Pins objects to local storage", ShortDescription: ` Retrieves the object named by and stores it locally on disk. `, }, Arguments: []cmds.Argument{ cmds.StringArg("ipfs-path", true, true, "Path to object(s) to be pinned").EnableStdin(), }, Options: []cmds.Option{ cmds.BoolOption("recursive", "r", "Recursively pin the object linked to by the specified object(s)"), }, Type: PinOutput{}, Run: func(req cmds.Request) (interface{}, error) { n, err := req.Context().GetNode() if err != nil { return nil, err } // set recursive flag recursive, found, err := req.Option("recursive").Bool() if err != nil { return nil, err } if !found { recursive = false } added, err := corerepo.Pin(n, req.Arguments(), recursive) if err != nil { return nil, err } return &PinOutput{added}, nil }, Marshalers: cmds.MarshalerMap{ cmds.Text: func(res cmds.Response) (io.Reader, error) { added, ok := res.Output().(*PinOutput) if !ok { return nil, u.ErrCast() } buf := new(bytes.Buffer) for _, k := range added.Pinned { fmt.Fprintf(buf, "Pinned %s\n", k) } return buf, nil }, }, } var rmPinCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Unpin an object from local storage", ShortDescription: ` Removes the pin from the given object allowing it to be garbage collected if needed. `, }, Arguments: []cmds.Argument{ cmds.StringArg("ipfs-path", true, true, "Path to object(s) to be unpinned").EnableStdin(), }, Options: []cmds.Option{ cmds.BoolOption("recursive", "r", "Recursively unpin the object linked to by the specified object(s)"), }, Type: PinOutput{}, Run: func(req cmds.Request) (interface{}, error) { n, err := req.Context().GetNode() if err != nil { return nil, err } // set recursive flag recursive, found, err := req.Option("recursive").Bool() if err != nil { return nil, err } if !found { recursive = false // default } removed, err := corerepo.Unpin(n, req.Arguments(), recursive) if err != nil { return nil, err } return &PinOutput{removed}, nil }, Marshalers: cmds.MarshalerMap{ cmds.Text: func(res cmds.Response) (io.Reader, error) { added, ok := res.Output().(*PinOutput) if !ok { return nil, u.ErrCast() } buf := new(bytes.Buffer) for _, k := range added.Pinned { fmt.Fprintf(buf, "Unpinned %s\n", k) } return buf, nil }, }, } var listPinCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "List objects pinned to local storage", ShortDescription: ` Returns a list of hashes of objects being pinned. Objects that are indirectly or recursively pinned are not included in the list. `, LongDescription: ` Returns a list of hashes of objects being pinned. Objects that are indirectly or recursively pinned are not included in the list. Use --type= to specify the type of pinned keys to list. Valid values are: * "direct" * "indirect" * "recursive" * "all" (Defaults to "direct") `, }, Options: []cmds.Option{ cmds.StringOption("type", "t", "The type of pinned keys to list. Can be \"direct\", \"indirect\", \"recursive\", or \"all\". Defaults to \"direct\""), }, Run: func(req cmds.Request) (interface{}, error) { n, err := req.Context().GetNode() if err != nil { return nil, err } typeStr, found, err := req.Option("type").String() if err != nil { return nil, err } if !found { typeStr = "direct" } switch typeStr { case "all", "direct", "indirect", "recursive": default: return nil, cmds.ClientError("Invalid type '" + typeStr + "', must be one of {direct, indirect, recursive, all}") } keys := make([]u.Key, 0) if typeStr == "direct" || typeStr == "all" { keys = append(keys, n.Pinning.DirectKeys()...) } if typeStr == "indirect" || typeStr == "all" { keys = append(keys, n.Pinning.IndirectKeys()...) } if typeStr == "recursive" || typeStr == "all" { keys = append(keys, n.Pinning.RecursiveKeys()...) } return &KeyList{Keys: keys}, nil }, Type: KeyList{}, Marshalers: cmds.MarshalerMap{ cmds.Text: KeyListTextMarshaler, }, }