pin.go 3.27 KB
Newer Older
1 2 3 4 5 6
package commands

import (
	"fmt"

	cmds "github.com/jbenet/go-ipfs/commands"
Brian Tiger Chow's avatar
Brian Tiger Chow committed
7
	"github.com/jbenet/go-ipfs/core"
Brian Tiger Chow's avatar
Brian Tiger Chow committed
8
	"github.com/jbenet/go-ipfs/core/commands2/internal"
Brian Tiger Chow's avatar
Brian Tiger Chow committed
9
	"github.com/jbenet/go-ipfs/merkledag"
10 11 12
)

var pinCmd = &cmds.Command{
13 14
	Description: "Keeps objects stored locally",

Brian Tiger Chow's avatar
Brian Tiger Chow committed
15 16 17 18 19 20 21
	Subcommands: map[string]*cmds.Command{
		"add": addPinCmd,
		"rm":  rmPinCmd,
	},
}

var addPinCmd = &cmds.Command{
22 23 24
	Description: "Pins objects to local storage",
	Help: `Keeps the object(s) named by <ipfs-path> in local storage. If the object
isn't already being stored, IPFS retrieves it.
Brian Tiger Chow's avatar
Brian Tiger Chow committed
25
`,
26

27
	Arguments: []cmds.Argument{
28 29 30 31 32 33
		cmds.Argument{"ipfs-path", cmds.ArgString, true, true,
			"Path to object(s) to be pinned"},
	},
	Options: []cmds.Option{
		cmds.Option{[]string{"recursive", "r"}, cmds.Bool,
			"Recursively pin the object linked to by the specified object(s)"},
34 35 36 37 38 39 40 41
	},
	Run: func(res cmds.Response, req cmds.Request) {
		n := req.Context().Node

		// set recursive flag
		opt, _ := req.Option("recursive")
		recursive, _ := opt.(bool) // false if cast fails.

Brian Tiger Chow's avatar
Brian Tiger Chow committed
42
		paths, err := internal.ToStrings(req.Arguments())
Brian Tiger Chow's avatar
Brian Tiger Chow committed
43 44 45
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
46 47
		}

Brian Tiger Chow's avatar
Brian Tiger Chow committed
48
		_, err = pin(n, paths, recursive)
49 50 51 52 53 54 55 56
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
		}

		// TODO: create some output to show what got pinned
	},
}

Brian Tiger Chow's avatar
Brian Tiger Chow committed
57
var rmPinCmd = &cmds.Command{
58 59
	Description: "Unpin an object from local storage",
	Help: `Removes the pin from the given object allowing it to be garbage
Brian Tiger Chow's avatar
Brian Tiger Chow committed
60 61
	collected if needed.
`,
62

63
	Arguments: []cmds.Argument{
64 65 66 67 68 69
		cmds.Argument{"ipfs-path", cmds.ArgString, true, true,
			"Path to object(s) to be unpinned"},
	},
	Options: []cmds.Option{
		cmds.Option{[]string{"recursive", "r"}, cmds.Bool,
			"Recursively unpin the object linked to by the specified object(s)"},
70 71 72 73 74 75 76 77
	},
	Run: func(res cmds.Response, req cmds.Request) {
		n := req.Context().Node

		// set recursive flag
		opt, _ := req.Option("recursive")
		recursive, _ := opt.(bool) // false if cast fails.

Brian Tiger Chow's avatar
Brian Tiger Chow committed
78 79 80 81
		paths, err := internal.ToStrings(req.Arguments())
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
82 83
		}

Brian Tiger Chow's avatar
Brian Tiger Chow committed
84
		_, err = unpin(n, paths, recursive)
85 86 87 88 89 90 91
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
		}

		// TODO: create some output to show what got unpinned
	},
}
Brian Tiger Chow's avatar
Brian Tiger Chow committed
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117

func pin(n *core.IpfsNode, paths []string, recursive bool) ([]*merkledag.Node, error) {

	dagnodes := make([]*merkledag.Node, 0)
	for _, path := range paths {
		dagnode, err := n.Resolver.ResolvePath(path)
		if err != nil {
			return nil, fmt.Errorf("pin error: %v", err)
		}
		dagnodes = append(dagnodes, dagnode)
	}

	for _, dagnode := range dagnodes {
		err := n.Pinning.Pin(dagnode, recursive)
		if err != nil {
			return nil, fmt.Errorf("pin: %v", err)
		}
	}

	err := n.Pinning.Flush()
	if err != nil {
		return nil, err
	}

	return dagnodes, nil
}
Brian Tiger Chow's avatar
Brian Tiger Chow committed
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143

func unpin(n *core.IpfsNode, paths []string, recursive bool) ([]*merkledag.Node, error) {

	dagnodes := make([]*merkledag.Node, 0)
	for _, path := range paths {
		dagnode, err := n.Resolver.ResolvePath(path)
		if err != nil {
			return nil, err
		}
		dagnodes = append(dagnodes, dagnode)
	}

	for _, dagnode := range dagnodes {
		k, _ := dagnode.Key()
		err := n.Pinning.Unpin(k, recursive)
		if err != nil {
			return nil, err
		}
	}

	err := n.Pinning.Flush()
	if err != nil {
		return nil, err
	}
	return dagnodes, nil
}