2
2
mirror of https://github.com/octoleo/restic.git synced 2024-11-22 21:05:10 +00:00

Remove scanner (not needed any more)

This commit is contained in:
Alexander Neumann 2015-02-16 23:44:26 +01:00
parent 0a164ad5e0
commit d4cfa7b797
3 changed files with 35 additions and 173 deletions

View File

@ -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))
}
}

View File

@ -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
}

View File

@ -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)
}
}