initial implementation of repo-gc command
Jeromy committed
Jan 14, 2015 at 00:01 UTC
f0781d81197745e73814dbf0e2c985fe1658d645
3 files changed
+107
-2
core/commands/mount_unix.go
+1
-1
@@ -9,11 +9,11 @@ import (
9
"time"
10
11
cmds "github.com/jbenet/go-ipfs/commands"
12
- config "github.com/jbenet/go-ipfs/repo/config"
12
core "github.com/jbenet/go-ipfs/core"
13
ipns "github.com/jbenet/go-ipfs/fuse/ipns"
14
mount "github.com/jbenet/go-ipfs/fuse/mount"
15
rofs "github.com/jbenet/go-ipfs/fuse/readonly"
16
+ config "github.com/jbenet/go-ipfs/repo/config"
17
)
18
19
// amount of time to wait for mount errors
core/commands/repo.go
new
+104
@@ -0,0 +1,104 @@
1
+package commands
2
+
3
+import (
4
+ "bytes"
5
+ "fmt"
6
+ "io"
7
+ cmds "github.com/jbenet/go-ipfs/commands"
8
+ "github.com/jbenet/go-ipfs/core"
9
+ u "github.com/jbenet/go-ipfs/util"
10
+)
11
+
12
+var RepoCmd = &cmds.Command{
13
+ Helptext: cmds.HelpText{
14
+ Tagline: "Manipulate the IPFS repo",
15
+ ShortDescription: `
16
+'ipfs repo' is a plumbing command used to manipulate the repo.
17
+`,
18
+ },
19
+
20
+ Subcommands: map[string]*cmds.Command{
21
+ "gc": repoGcCmd,
22
+ },
23
+}
24
+
25
+type KeyRemoved struct {
26
+ Key u.Key
27
+}
28
+
29
+var repoGcCmd = &cmds.Command{
30
+ Helptext: cmds.HelpText{
31
+ Tagline: "Perform a garbage collection sweep on the repo",
32
+ ShortDescription: `
33
+'ipfs repo gc' is a plumbing command that will sweep the local
34
+set of stored objects and remove ones that are not pinned in
35
+order to reclaim hard disk space.
36
+`,
37
+ },
38
+
39
+ Options: []cmds.Option{
40
+ cmds.BoolOption("quiet", "q", "Write minimal output"),
41
+ },
42
+ Run: func(req cmds.Request) (interface{}, error) {
43
+ n, err := req.Context().GetNode()
44
+ if err != nil {
45
+ return nil, err
46
+ }
47
+
48
+ keychan, err := n.Blockstore.AllKeysChan(req.Context().Context, 0, 1<<16)
49
+ if err != nil {
50
+ return nil, err
51
+ }
52
+
53
+ outChan := make(chan interface{})
54
+ go GarbageCollectBlockstore(n, keychan, outChan)
55
+ return outChan, nil
56
+ },
57
+ Type: KeyRemoved{},
58
+ Marshalers: cmds.MarshalerMap{
59
+ cmds.Text: func(res cmds.Response) (io.Reader, error) {
60
+ outChan, ok := res.Output().(chan interface{})
61
+ if !ok {
62
+ return nil, u.ErrCast()
63
+ }
64
+
65
+ quiet, _, err := res.Request().Option("quiet").Bool()
66
+ if err != nil {
67
+ return nil, err
68
+ }
69
+
70
+ marshal := func(v interface{}) (io.Reader, error) {
71
+ obj, ok := v.(*KeyRemoved)
72
+ if !ok {
73
+ return nil, u.ErrCast()
74
+ }
75
+
76
+ var buf *bytes.Buffer
77
+ if quiet {
78
+ buf = bytes.NewBufferString(string(obj.Key) + "\n")
79
+ } else {
80
+ buf = bytes.NewBufferString(fmt.Sprintf("removed %s\n", obj.Key))
81
+ }
82
+ return buf, nil
83
+ }
84
+
85
+ return &cmds.ChannelMarshaler{
86
+ Channel: outChan,
87
+ Marshaler: marshal,
88
+ }, nil
89
+ },
90
+ },
91
+}
92
+
93
+func GarbageCollectBlockstore(n *core.IpfsNode, keychan <-chan u.Key, output chan interface{}) {
94
+ defer close(output)
95
+ for k := range keychan {
96
+ if !n.Pinning.IsPinned(k) {
97
+ err := n.Blockstore.DeleteBlock(k)
98
+ if err != nil {
99
+ log.Errorf("Error removing key from blockstore: %s", err)
100
+ }
101
+ output <- &KeyRemoved{k}
102
+ }
103
+ }
104
+}
core/commands/root.go
+2
-1
@@ -79,9 +79,10 @@ var rootSubcommands = map[string]*cmds.Command{
79
"name": NameCmd,
80
"object": ObjectCmd,
81
"pin": PinCmd,
82
+ "ping": PingCmd,
83
"refs": RefsCmd,
84
+ "repo": RepoCmd,
85
"swarm": SwarmCmd,
84
- "ping": PingCmd,
86
"update": UpdateCmd,
87
"version": VersionCmd,
88
}