forked from TrueCloudLab/restic
Remove scanner (not needed any more)
This commit is contained in:
parent
0a164ad5e0
commit
d4cfa7b797
3 changed files with 35 additions and 173 deletions
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -73,6 +74,10 @@ func (cmd CmdBackup) Usage() string {
|
|||
return "DIR/FILE [snapshot-ID]"
|
||||
}
|
||||
|
||||
func isFile(fi os.FileInfo) bool {
|
||||
return fi.Mode()&(os.ModeType|os.ModeCharDevice) == 0
|
||||
}
|
||||
|
||||
func (cmd CmdBackup) Execute(args []string) error {
|
||||
if len(args) == 0 || len(args) > 2 {
|
||||
return fmt.Errorf("wrong number of parameters, Usage: %s", cmd.Usage())
|
||||
|
@ -112,54 +117,59 @@ func (cmd CmdBackup) Execute(args []string) error {
|
|||
// return true
|
||||
// }
|
||||
|
||||
sc := restic.NewScanner(scanProgress)
|
||||
stat := restic.Stat{}
|
||||
|
||||
term := terminal.IsTerminal(int(os.Stdout.Fd()))
|
||||
|
||||
start := time.Now()
|
||||
err = filepath.Walk(target, func(p string, fi os.FileInfo, err error) error {
|
||||
if isFile(fi) {
|
||||
stat.Files++
|
||||
stat.Bytes += uint64(fi.Size())
|
||||
} else if fi.IsDir() {
|
||||
stat.Dirs++
|
||||
}
|
||||
|
||||
if term {
|
||||
fmt.Printf("\x1b[2K\r[%s] %d directories, %d files, %s",
|
||||
format_duration(time.Since(start)), stat.Dirs, stat.Files, format_bytes(stat.Bytes))
|
||||
}
|
||||
|
||||
// TODO: handle error?
|
||||
return nil
|
||||
})
|
||||
|
||||
newTree, err := sc.Scan(target)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("\nDone in %s\n", format_duration(time.Since(start)))
|
||||
|
||||
if parentSnapshotID != nil {
|
||||
fmt.Printf("load old snapshot\n")
|
||||
sn, err := restic.LoadSnapshot(s, parentSnapshotID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
oldTree, err := restic.LoadTreeRecursive(filepath.Dir(sn.Dir), s, sn.Tree)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = newTree.CopyFrom(oldTree, &s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
archiveProgress := restic.NewProgress(time.Second)
|
||||
targetStat := newTree.StatTodo()
|
||||
|
||||
if terminal.IsTerminal(int(os.Stdout.Fd())) {
|
||||
var bps, eta uint64
|
||||
itemsTodo := targetStat.Files + targetStat.Dirs
|
||||
itemsTodo := stat.Files + stat.Dirs
|
||||
|
||||
archiveProgress.OnUpdate = func(s restic.Stat, d time.Duration, ticker bool) {
|
||||
sec := uint64(d / time.Second)
|
||||
if targetStat.Bytes > 0 && sec > 0 && ticker {
|
||||
if stat.Bytes > 0 && sec > 0 && ticker {
|
||||
bps = s.Bytes / sec
|
||||
if bps > 0 {
|
||||
eta = (targetStat.Bytes - s.Bytes) / bps
|
||||
eta = (stat.Bytes - s.Bytes) / bps
|
||||
}
|
||||
}
|
||||
|
||||
itemsDone := s.Files + s.Dirs
|
||||
fmt.Printf("\x1b[2K\r[%s] %3.2f%% %s/s %s / %s %d / %d items ETA %s",
|
||||
format_duration(d),
|
||||
float64(s.Bytes)/float64(targetStat.Bytes)*100,
|
||||
float64(s.Bytes)/float64(stat.Bytes)*100,
|
||||
format_bytes(bps),
|
||||
format_bytes(s.Bytes), format_bytes(targetStat.Bytes),
|
||||
format_bytes(s.Bytes), format_bytes(stat.Bytes),
|
||||
itemsDone, itemsTodo,
|
||||
format_seconds(eta))
|
||||
}
|
||||
|
@ -168,7 +178,7 @@ func (cmd CmdBackup) Execute(args []string) error {
|
|||
sec := uint64(d / time.Second)
|
||||
fmt.Printf("\nduration: %s, %.2fMiB/s\n",
|
||||
format_duration(d),
|
||||
float64(targetStat.Bytes)/float64(sec)/(1<<20))
|
||||
float64(stat.Bytes)/float64(sec)/(1<<20))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
119
scanner.go
119
scanner.go
|
@ -1,119 +0,0 @@
|
|||
package restic
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/juju/arrar"
|
||||
)
|
||||
|
||||
type FilterFunc func(item string, fi os.FileInfo) bool
|
||||
type ErrorFunc func(dir string, fi os.FileInfo, err error) error
|
||||
|
||||
type Scanner struct {
|
||||
Error ErrorFunc
|
||||
Filter FilterFunc
|
||||
|
||||
p *Progress
|
||||
}
|
||||
|
||||
func NewScanner(p *Progress) *Scanner {
|
||||
sc := &Scanner{p: p}
|
||||
|
||||
// abort on all errors
|
||||
sc.Error = func(s string, fi os.FileInfo, err error) error { return err }
|
||||
// allow all files
|
||||
sc.Filter = func(string, os.FileInfo) bool { return true }
|
||||
|
||||
return sc
|
||||
}
|
||||
|
||||
func scan(filterFn FilterFunc, progress *Progress, dir string) (*Tree, error) {
|
||||
var err error
|
||||
|
||||
// open and list path
|
||||
fd, err := os.Open(dir)
|
||||
defer fd.Close()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
entries, err := fd.Readdir(-1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// build new tree
|
||||
tree := NewTree()
|
||||
for _, entry := range entries {
|
||||
path := filepath.Join(dir, entry.Name())
|
||||
|
||||
if !filterFn(path, entry) {
|
||||
continue
|
||||
}
|
||||
|
||||
node, err := NodeFromFileInfo(path, entry)
|
||||
if err != nil {
|
||||
// TODO: error processing
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = tree.Insert(node)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if entry.IsDir() {
|
||||
// save all errors in node.err, sort out later
|
||||
node.tree, node.err = scan(filterFn, progress, path)
|
||||
}
|
||||
}
|
||||
|
||||
for _, node := range tree.Nodes {
|
||||
if node.Type == "file" && node.Content != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
switch node.Type {
|
||||
case "file":
|
||||
progress.Report(Stat{Files: 1, Bytes: node.Size})
|
||||
case "dir":
|
||||
progress.Report(Stat{Dirs: 1})
|
||||
}
|
||||
}
|
||||
|
||||
return tree, nil
|
||||
}
|
||||
|
||||
func (sc *Scanner) Scan(path string) (*Tree, error) {
|
||||
sc.p.Start()
|
||||
defer sc.p.Done()
|
||||
|
||||
fi, err := os.Lstat(path)
|
||||
if err != nil {
|
||||
return nil, arrar.Annotatef(err, "Lstat(%q)", path)
|
||||
}
|
||||
|
||||
node, err := NodeFromFileInfo(path, fi)
|
||||
if err != nil {
|
||||
return nil, arrar.Annotate(err, "NodeFromFileInfo()")
|
||||
}
|
||||
|
||||
tree := NewTree()
|
||||
tree.Insert(node)
|
||||
if node.Type != "dir" {
|
||||
sc.p.Report(Stat{Files: 1, Bytes: node.Size})
|
||||
|
||||
return tree, nil
|
||||
}
|
||||
|
||||
sc.p.Report(Stat{Dirs: 1})
|
||||
|
||||
node.tree, err = scan(sc.Filter, sc.p, path)
|
||||
if err != nil {
|
||||
return nil, arrar.Annotate(err, "loadTree()")
|
||||
}
|
||||
|
||||
return tree, nil
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package restic_test
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"testing"
|
||||
|
||||
"github.com/restic/restic"
|
||||
)
|
||||
|
||||
var scanDir = flag.String("test.scandir", ".", "test/benchmark scanning a real directory (default: .)")
|
||||
|
||||
func TestScanner(t *testing.T) {
|
||||
sc := restic.NewScanner(nil)
|
||||
|
||||
tree, err := sc.Scan(*scanDir)
|
||||
ok(t, err)
|
||||
|
||||
stats := tree.Stat()
|
||||
|
||||
assert(t, stats.Files > 0,
|
||||
"no files in dir %v", *scanDir)
|
||||
}
|
||||
|
||||
func BenchmarkScanner(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := restic.NewScanner(nil).Scan(*scanDir)
|
||||
ok(b, err)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue