repo-stat
License: MIT Signed-off-by: David Dias <daviddias.p@gmail.com>
David Dias committed
Mar 2, 2016 at 08:48 UTC
c10e329b789b931fa384d4cf83ad1d23d5cf1a57
3 files changed
+99
-43
core/commands/repo.go
+31
-43
@@ -3,22 +3,12 @@ package commands
3
import (
4
"bytes"
5
"fmt"
6
- "io"
7
- "strings"
8
-
9
- humanize "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/dustin/go-humanize"
6
cmds "github.com/ipfs/go-ipfs/commands"
7
corerepo "github.com/ipfs/go-ipfs/core/corerepo"
12
- fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo"
8
u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
9
+ "io"
10
)
11
16
-type RepoStat struct {
17
- repoPath string
18
- repoSize uint64 // size in bytes
19
- numBlocks uint64
20
-}
21
-
12
var RepoCmd = &cmds.Command{
13
Helptext: cmds.HelpText{
14
Tagline: "Manipulate the IPFS repo.",
@@ -108,59 +98,57 @@ order to reclaim hard disk space.
98
99
var repoStatCmd = &cmds.Command{
100
Helptext: cmds.HelpText{
111
- Tagline: "Print status of the local repo.",
112
- ShortDescription: ``,
101
+ Tagline: "Get stats for the currently used repo.",
102
+ ShortDescription: `
103
+'ipfs repo stat' is a plumbing command that will scan the local
104
+set of stored objects and print repo statistics. It outputs to stdout:
105
+NumObjects int number of objects in the local repo
106
+RepoSize int size in bytes that the repo is currently taking
107
+RepoPath string the path to the repo being currently used
108
+`,
109
},
110
Run: func(req cmds.Request, res cmds.Response) {
115
- ctx := req.Context()
111
n, err := req.InvocContext().GetNode()
112
if err != nil {
113
res.SetError(err, cmds.ErrNormal)
114
return
115
}
116
122
- usage, err := n.Repo.GetStorageUsage()
123
- if err != nil {
124
- res.SetError(err, cmds.ErrNormal)
125
- return
126
- }
127
-
128
- allKeys, err := n.Blockstore.AllKeysChan(ctx)
129
- if err != nil {
130
- res.SetError(err, cmds.ErrNormal)
131
- return
132
- }
133
-
134
- count := uint64(0)
135
- for range allKeys {
136
- count++
137
- }
138
-
139
- path, err := fsrepo.BestKnownPath()
117
+ stat, err := corerepo.RepoStat(n, req.Context())
118
if err != nil {
119
res.SetError(err, cmds.ErrNormal)
120
return
121
}
122
145
- res.SetOutput(&RepoStat{
146
- repoPath: path,
147
- repoSize: usage,
148
- numBlocks: count,
149
- })
123
+ res.SetOutput(stat)
124
},
151
- Type: RepoStat{},
125
+ Options: []cmds.Option{
126
+ cmds.BoolOption("human", "Output RepoSize in MiB."),
127
+ },
128
+ Type: corerepo.Stat{},
129
Marshalers: cmds.MarshalerMap{
130
cmds.Text: func(res cmds.Response) (io.Reader, error) {
154
- stat, ok := res.Output().(*RepoStat)
131
+ stat, ok := res.Output().(*corerepo.Stat)
132
if !ok {
133
return nil, u.ErrCast()
134
}
135
159
- out := fmt.Sprintf(
160
- "Path: %s\nSize: %s\nBlocks: %d\n",
161
- stat.repoPath, humanize.Bytes(stat.repoSize), stat.numBlocks)
136
+ human, _, err := res.Request().Option("human").Bool()
137
+ if err != nil {
138
+ return nil, err
139
+ }
140
+
141
+ buf := new(bytes.Buffer)
142
+ fmt.Fprintf(buf, "NumObjects \t %d\n", stat.NumObjects)
143
+ sizeInMiB := stat.RepoSize / (1024 * 1024)
144
+ if human && sizeInMiB > 0 {
145
+ fmt.Fprintf(buf, "RepoSize (MiB) \t %d\n", sizeInMiB)
146
+ } else {
147
+ fmt.Fprintf(buf, "RepoSize \t %d\n", stat.RepoSize)
148
+ }
149
+ fmt.Fprintf(buf, "RepoPath \t %s\n", stat.RepoPath)
150
163
- return strings.NewReader(out), nil
151
+ return buf, nil
152
},
153
},
154
}
core/corerepo/stat.go
new
+43
@@ -0,0 +1,43 @@
1
+package corerepo
2
+
3
+import (
4
+ "github.com/ipfs/go-ipfs/core"
5
+ fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo"
6
+ context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
7
+)
8
+
9
+type Stat struct {
10
+ NumObjects uint64
11
+ RepoSize uint64 // size in bytes
12
+ RepoPath string
13
+}
14
+
15
+func RepoStat(n *core.IpfsNode, ctx context.Context) (*Stat, error) {
16
+ r := n.Repo
17
+
18
+ usage, err := r.GetStorageUsage()
19
+ if err != nil {
20
+ return nil, err
21
+ }
22
+
23
+ allKeys, err := n.Blockstore.AllKeysChan(ctx)
24
+ if err != nil {
25
+ return nil, err
26
+ }
27
+
28
+ count := uint64(0)
29
+ for range allKeys {
30
+ count++
31
+ }
32
+
33
+ path, err := fsrepo.BestKnownPath()
34
+ if err != nil {
35
+ return nil, err
36
+ }
37
+
38
+ return &Stat{
39
+ NumObjects: count,
40
+ RepoSize: usage,
41
+ RepoPath: path,
42
+ }, nil
43
+}
test/sharness/t0080-repo.sh
+25
@@ -219,6 +219,31 @@ test_expect_success "'ipfs refs --unique --recursive (bigger)'" '
219
test_sort_cmp expected actual || test_fsh cat refs_output
220
'
221
222
+get_field_num() {
223
+ field=$1
224
+ file=$2
225
+ num=$(grep "$field" "$file" | awk '{ print $2 }')
226
+ echo $num
227
+}
228
+
229
+test_expect_success "'ipfs repo stat' succeeds" '
230
+ ipfs repo stat > repo-stats
231
+'
232
+test_expect_success "repo stats came out correct" '
233
+ grep "RepoPath" repo-stats &&
234
+ grep "RepoSize" repo-stats &&
235
+ grep "NumObjects" repo-stats
236
+'
237
+
238
+test_expect_success "'ipfs repo stat' after adding a file" '
239
+ ipfs add repo-stats &&
240
+ ipfs repo stat > repo-stats-2
241
+'
242
+
243
+test_expect_success "repo stats are updated correctly" '
244
+ test $(get_field_num "RepoSize" repo-stats-2) -ge $(get_field_num "RepoSize" repo-stats)
245
+'
246
+
247
test_kill_ipfs_daemon
248
249
test_done