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
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -73,6 +74,10 @@ func (cmd CmdBackup) Usage() string {
|
||||||
return "DIR/FILE [snapshot-ID]"
|
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 {
|
func (cmd CmdBackup) Execute(args []string) error {
|
||||||
if len(args) == 0 || len(args) > 2 {
|
if len(args) == 0 || len(args) > 2 {
|
||||||
return fmt.Errorf("wrong number of parameters, Usage: %s", cmd.Usage())
|
return fmt.Errorf("wrong number of parameters, Usage: %s", cmd.Usage())
|
||||||
|
@ -112,54 +117,59 @@ func (cmd CmdBackup) Execute(args []string) error {
|
||||||
// return true
|
// 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 {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Printf("\nDone in %s\n", format_duration(time.Since(start)))
|
||||||
|
|
||||||
if parentSnapshotID != nil {
|
if parentSnapshotID != nil {
|
||||||
fmt.Printf("load old snapshot\n")
|
return errors.New("not implemented")
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
archiveProgress := restic.NewProgress(time.Second)
|
archiveProgress := restic.NewProgress(time.Second)
|
||||||
targetStat := newTree.StatTodo()
|
|
||||||
|
|
||||||
if terminal.IsTerminal(int(os.Stdout.Fd())) {
|
if terminal.IsTerminal(int(os.Stdout.Fd())) {
|
||||||
var bps, eta uint64
|
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) {
|
archiveProgress.OnUpdate = func(s restic.Stat, d time.Duration, ticker bool) {
|
||||||
sec := uint64(d / time.Second)
|
sec := uint64(d / time.Second)
|
||||||
if targetStat.Bytes > 0 && sec > 0 && ticker {
|
if stat.Bytes > 0 && sec > 0 && ticker {
|
||||||
bps = s.Bytes / sec
|
bps = s.Bytes / sec
|
||||||
if bps > 0 {
|
if bps > 0 {
|
||||||
eta = (targetStat.Bytes - s.Bytes) / bps
|
eta = (stat.Bytes - s.Bytes) / bps
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
itemsDone := s.Files + s.Dirs
|
itemsDone := s.Files + s.Dirs
|
||||||
fmt.Printf("\x1b[2K\r[%s] %3.2f%% %s/s %s / %s %d / %d items ETA %s",
|
fmt.Printf("\x1b[2K\r[%s] %3.2f%% %s/s %s / %s %d / %d items ETA %s",
|
||||||
format_duration(d),
|
format_duration(d),
|
||||||
float64(s.Bytes)/float64(targetStat.Bytes)*100,
|
float64(s.Bytes)/float64(stat.Bytes)*100,
|
||||||
format_bytes(bps),
|
format_bytes(bps),
|
||||||
format_bytes(s.Bytes), format_bytes(targetStat.Bytes),
|
format_bytes(s.Bytes), format_bytes(stat.Bytes),
|
||||||
itemsDone, itemsTodo,
|
itemsDone, itemsTodo,
|
||||||
format_seconds(eta))
|
format_seconds(eta))
|
||||||
}
|
}
|
||||||
|
@ -168,7 +178,7 @@ func (cmd CmdBackup) Execute(args []string) error {
|
||||||
sec := uint64(d / time.Second)
|
sec := uint64(d / time.Second)
|
||||||
fmt.Printf("\nduration: %s, %.2fMiB/s\n",
|
fmt.Printf("\nduration: %s, %.2fMiB/s\n",
|
||||||
format_duration(d),
|
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