restic/cmd/khepri/cmd_fsck.go

87 lines
1.5 KiB
Go

package main
import (
"crypto/sha256"
"encoding/json"
"log"
"github.com/fd0/khepri"
)
func fsck_tree(repo *khepri.Repository, id khepri.ID) (bool, error) {
log.Printf(" checking dir %s", id)
rd, err := repo.Get(khepri.TYPE_BLOB, id)
if err != nil {
return false, err
}
hr := khepri.NewHashingReader(rd, sha256.New)
dec := json.NewDecoder(hr)
tree := &khepri.Tree{}
err = dec.Decode(tree)
if err != nil {
return false, err
}
if !id.Equal(hr.Hash()) {
return false, nil
}
return true, nil
}
func fsck_snapshot(repo *khepri.Repository, id khepri.ID) (bool, error) {
log.Printf("checking snapshot %s", id)
sn, err := khepri.LoadSnapshot(repo, id)
if err != nil {
return false, err
}
return fsck_tree(repo, sn.Content)
}
func commandFsck(repo *khepri.Repository, args []string) error {
var snapshots khepri.IDs
var err error
if len(args) != 0 {
snapshots = make(khepri.IDs, 0, len(args))
for _, arg := range args {
id, err := khepri.ParseID(arg)
if err != nil {
log.Fatal(err)
}
snapshots = append(snapshots, id)
}
} else {
snapshots, err = repo.List(khepri.TYPE_REF)
if err != nil {
log.Fatalf("error reading list of snapshot IDs: %v", err)
}
}
log.Printf("checking %d snapshots", len(snapshots))
for _, id := range snapshots {
ok, err := fsck_snapshot(repo, id)
if err != nil {
log.Printf("error checking snapshot %s: %v", id, err)
continue
}
if !ok {
log.Printf("snapshot %s failed", id)
}
}
return nil
}