add repo verify command
License: MIT Signed-off-by: Jeromy <why@ipfs.io>
Jeromy committed
Jun 30, 2016 at 18:09 UTC
c53154cd2bcfe0a33a231e04da32dd0366484ace
1 file changed
+89
-6
core/commands/repo.go
+89
-6
@@ -3,15 +3,18 @@ package commands
3
import (
4
"bytes"
5
"fmt"
6
+ "io"
7
+ "os"
8
+ "path/filepath"
9
+
10
+ bstore "github.com/ipfs/go-ipfs/blocks/blockstore"
11
cmds "github.com/ipfs/go-ipfs/commands"
12
corerepo "github.com/ipfs/go-ipfs/core/corerepo"
13
config "github.com/ipfs/go-ipfs/repo/config"
14
fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo"
15
lockfile "github.com/ipfs/go-ipfs/repo/fsrepo/lock"
16
+
17
u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
12
- "io"
13
- "os"
14
- "path/filepath"
18
)
19
20
type RepoVersion struct {
@@ -31,6 +34,7 @@ var RepoCmd = &cmds.Command{
34
"stat": repoStatCmd,
35
"fsck": RepoFsckCmd,
36
"version": repoVersionCmd,
37
+ "verify": repoVerifyCmd,
38
},
39
}
40
@@ -207,9 +211,7 @@ daemons are running.
211
return
212
}
213
210
- s := "Lockfiles have been removed."
211
- log.Info(s)
212
- res.SetOutput(&MessageOutput{s + "\n"})
214
+ res.SetOutput(&MessageOutput{"Lockfiles have been removed.\n"})
215
},
216
Type: MessageOutput{},
217
Marshalers: cmds.MarshalerMap{
@@ -217,6 +219,87 @@ daemons are running.
219
},
220
}
221
222
+type VerifyProgress struct {
223
+ Message string
224
+ Progress int
225
+}
226
+
227
+var repoVerifyCmd = &cmds.Command{
228
+ Helptext: cmds.HelpText{
229
+ Tagline: "Verify all blocks in repo are not corrupted.",
230
+ },
231
+ Run: func(req cmds.Request, res cmds.Response) {
232
+ nd, err := req.InvocContext().GetNode()
233
+ if err != nil {
234
+ res.SetError(err, cmds.ErrNormal)
235
+ return
236
+ }
237
+
238
+ out := make(chan interface{})
239
+ go func() {
240
+ defer close(out)
241
+ bs := bstore.NewBlockstore(nd.Repo.Datastore())
242
+
243
+ bs.RuntimeHashing(true)
244
+
245
+ keys, err := bs.AllKeysChan(req.Context())
246
+ if err != nil {
247
+ log.Error(err)
248
+ return
249
+ }
250
+
251
+ var fails int
252
+ var i int
253
+ for k := range keys {
254
+ _, err := bs.Get(k)
255
+ if err != nil {
256
+ out <- &VerifyProgress{
257
+ Message: fmt.Sprintf("block %s was corrupt (%s)", k, err),
258
+ }
259
+ fails++
260
+ }
261
+ i++
262
+ out <- &VerifyProgress{Progress: i}
263
+ }
264
+ if fails == 0 {
265
+ out <- &VerifyProgress{Message: "verify complete, all blocks validated."}
266
+ }
267
+ }()
268
+
269
+ res.SetOutput((<-chan interface{})(out))
270
+ },
271
+ Marshalers: cmds.MarshalerMap{
272
+ cmds.Text: func(res cmds.Response) (io.Reader, error) {
273
+ out := res.Output().(<-chan interface{})
274
+
275
+ marshal := func(v interface{}) (io.Reader, error) {
276
+ obj, ok := v.(*VerifyProgress)
277
+ if !ok {
278
+ return nil, u.ErrCast()
279
+ }
280
+
281
+ buf := new(bytes.Buffer)
282
+ if obj.Message != "" {
283
+ if len(obj.Message) < 20 {
284
+ obj.Message += " "
285
+ }
286
+ fmt.Fprintln(buf, obj.Message)
287
+ return buf, nil
288
+ }
289
+
290
+ fmt.Fprintf(buf, "%d blocks processed.\r", obj.Progress)
291
+ return buf, nil
292
+ }
293
+
294
+ return &cmds.ChannelMarshaler{
295
+ Channel: out,
296
+ Marshaler: marshal,
297
+ Res: res,
298
+ }, nil
299
+ },
300
+ },
301
+}
302
+
303
var repoVersionCmd = &cmds.Command{
304
Helptext: cmds.HelpText{
305
Tagline: "Show the repo version.",