diff --git a/archiver.go b/archiver.go index aa75fa6f4..ddf35423e 100644 --- a/archiver.go +++ b/archiver.go @@ -11,6 +11,7 @@ import ( "github.com/juju/arrar" "github.com/restic/restic/backend" "github.com/restic/restic/chunker" + "github.com/restic/restic/debug" ) const ( @@ -64,12 +65,12 @@ func (arch *Archiver) Save(t backend.Type, data []byte) (Blob, error) { // compute plaintext hash id := backend.Hash(data) - debug("Archiver.Save", "Save(%v, %v)\n", t, id.Str()) + debug.Log("Archiver.Save", "Save(%v, %v)\n", t, id.Str()) // test if this blob is already known blob, err := arch.m.FindID(id) if err == nil { - debug("Archiver.Save", "Save(%v, %v): reusing %v\n", t, id.Str(), blob.Storage.Str()) + debug.Log("Archiver.Save", "Save(%v, %v): reusing %v\n", t, id.Str(), blob.Storage.Str()) id.Free() return blob, nil } @@ -84,7 +85,7 @@ func (arch *Archiver) Save(t backend.Type, data []byte) (Blob, error) { // one and remove the other. This happens if the same plaintext blob was // stored concurrently and finished earlier than this blob. if blob.Storage.Compare(smapblob.Storage) != 0 { - debug("Archiver.Save", "using other block, removing %v\n", blob.Storage.Str()) + debug.Log("Archiver.Save", "using other block, removing %v\n", blob.Storage.Str()) // remove the blob again // TODO: implement a list of blobs in transport, so this doesn't happen so often @@ -94,7 +95,7 @@ func (arch *Archiver) Save(t backend.Type, data []byte) (Blob, error) { } } - debug("Archiver.Save", "Save(%v, %v): new blob %v\n", t, id.Str(), blob) + debug.Log("Archiver.Save", "Save(%v, %v): new blob %v\n", t, id.Str(), blob) return smapblob, nil } @@ -254,13 +255,13 @@ func (arch *Archiver) SaveFile(node *Node) (Blobs, error) { return nil, fmt.Errorf("errors saving node %q: saved %d bytes, wanted %d bytes", node.path, bytes, node.Size) } - debug("Archiver.SaveFile", "SaveFile(%q): %v\n", node.path, blobs) + debug.Log("Archiver.SaveFile", "SaveFile(%q): %v\n", node.path, blobs) return blobs, nil } func (arch *Archiver) saveTree(t *Tree) (Blob, error) { - debug("Archiver.saveTree", "saveTree(%v)\n", t) + debug.Log("Archiver.saveTree", "saveTree(%v)\n", t) var wg sync.WaitGroup // add all blobs to global map @@ -284,7 +285,7 @@ func (arch *Archiver) saveTree(t *Tree) (Blob, error) { for _, id := range node.Content { blob, err := t.Map.FindID(id) if err != nil { - debug("Archiver.saveTree", "unable to find storage id for data blob %v", id.Str()) + debug.Log("Archiver.saveTree", "unable to find storage id for data blob %v", id.Str()) arch.Error(node.path, nil, fmt.Errorf("unable to find storage id for data blob %v", id.Str())) removeContent = true t.Map.DeleteID(id) @@ -293,7 +294,7 @@ func (arch *Archiver) saveTree(t *Tree) (Blob, error) { } if ok, err := arch.s.Test(backend.Data, blob.Storage); !ok || err != nil { - debug("Archiver.saveTree", "blob %v not in repository (error is %v)", blob, err) + debug.Log("Archiver.saveTree", "blob %v not in repository (error is %v)", blob, err) arch.Error(node.path, nil, fmt.Errorf("blob %v not in repository (error is %v)", blob.Storage.Str(), err)) removeContent = true t.Map.DeleteID(id) @@ -302,7 +303,7 @@ func (arch *Archiver) saveTree(t *Tree) (Blob, error) { } if removeContent { - debug("Archiver.saveTree", "removing content for %s", node.path) + debug.Log("Archiver.saveTree", "removing content for %s", node.path) node.Content = node.Content[:0] } } @@ -368,7 +369,7 @@ func (arch *Archiver) saveTree(t *Tree) (Blob, error) { after := len(t.Map.IDs()) if before != after { - debug("Archiver.saveTree", "pruned %d ids from map for tree %v\n", before-after, t) + debug.Log("Archiver.saveTree", "pruned %d ids from map for tree %v\n", before-after, t) } blob, err := arch.SaveTreeJSON(t) @@ -380,7 +381,7 @@ func (arch *Archiver) saveTree(t *Tree) (Blob, error) { } func (arch *Archiver) Snapshot(dir string, t *Tree, parentSnapshot backend.ID) (*Snapshot, backend.ID, error) { - debug_break("Archiver.Snapshot") + debug.Break("Archiver.Snapshot") arch.p.Start() defer arch.p.Done() diff --git a/cmd/gentestdata/main.go b/cmd/gentestdata/main.go new file mode 100644 index 000000000..4f0388d34 --- /dev/null +++ b/cmd/gentestdata/main.go @@ -0,0 +1,69 @@ +package main + +import ( + "fmt" + "io" + "math/rand" + "os" + "path/filepath" +) + +const ( + MaxFiles = 23 + MaxDepth = 3 +) + +var urnd *os.File + +func init() { + f, err := os.Open("/dev/urandom") + if err != nil { + panic(err) + } + + urnd = f +} + +func rndRd(bytes int) io.Reader { + return io.LimitReader(urnd, int64(bytes)) +} + +func create_dir(target string, depth int) { + fmt.Printf("create_dir %s, depth %d\n", target, depth) + err := os.Mkdir(target, 0755) + if err != nil && !os.IsExist(err) { + panic(err) + } + + for i := 0; i < MaxFiles; i++ { + if depth == 0 { + filename := filepath.Join(target, fmt.Sprintf("file%d", i)) + fmt.Printf("create file %v\n", filename) + f, err := os.Create(filename) + if err != nil { + panic(err) + } + + _, err = io.Copy(f, rndRd(rand.Intn(1024))) + if err != nil { + panic(err) + } + + err = f.Close() + if err != nil { + panic(err) + } + } else { + create_dir(filepath.Join(target, fmt.Sprintf("dir%d", i)), depth-1) + } + } +} + +func main() { + if len(os.Args) != 2 { + fmt.Fprintf(os.Stderr, "USAGE: %s TARGETDIR\n", os.Args[0]) + os.Exit(1) + } + + create_dir(os.Args[1], MaxDepth) +} diff --git a/cmd/ram/main.go b/cmd/ram/main.go new file mode 100644 index 000000000..3d1b4ca00 --- /dev/null +++ b/cmd/ram/main.go @@ -0,0 +1,26 @@ +package main + +import ( + "os" + + "github.com/restic/restic" +) + +func main() { + max := int(1e6) + nodes := make([]*restic.Node, 0, max) + + fi, err := os.Lstat("main.go") + if err != nil { + panic(err) + } + + for i := 0; i < max; i++ { + node, err := restic.NodeFromFileInfo("main.go", fi) + if err != nil { + panic(err) + } + + nodes = append(nodes, node) + } +} diff --git a/cmd/restic/Makefile b/cmd/restic/Makefile index 7294860e6..6e0e521c2 100644 --- a/cmd/restic/Makefile +++ b/cmd/restic/Makefile @@ -2,6 +2,7 @@ VERSION = $(shell ./version.sh) VERSION ?= "unknown version" LDFLAGS = -X main.version $(VERSION) +LDFLAGS += -X github.com/restic/restic.Version $(VERSION) TAGS = .PHONY: all both clean debug @@ -19,7 +20,7 @@ restic: $(wildcard *.go) $(wildcard ../../*.go) $(wildcard ../../*/*.go) go build -tags "$(TAGS)" $(GOFLAGS) -ldflags "$(LDFLAGS)" restic.debug: $(wildcard *.go) $(wildcard ../../*.go) $(wildcard ../../*/*.go) - go build -o restic.debug -tags "debug" $(GOFLAGS) -ldflags "$(LDFLAGS)" + go build -o restic.debug -tags "debug debug_cmd" $(GOFLAGS) -ldflags "$(LDFLAGS)" clean: go clean diff --git a/cmd/restic/cmd_find.go b/cmd/restic/cmd_find.go index d3111f1d2..fc1199ab6 100644 --- a/cmd/restic/cmd_find.go +++ b/cmd/restic/cmd_find.go @@ -7,6 +7,7 @@ import ( "github.com/restic/restic" "github.com/restic/restic/backend" + "github.com/restic/restic/debug" ) type findQuery struct { @@ -64,7 +65,7 @@ func parseTime(str string) (time.Time, error) { } func (c CmdFind) findInTree(s restic.Server, blob restic.Blob, path string) ([]findResult, error) { - debug("checking tree %v\n", blob) + debug.Log("restic.find", "checking tree %v\n", blob) tree, err := restic.LoadTree(s, blob) if err != nil { return nil, err @@ -72,7 +73,7 @@ func (c CmdFind) findInTree(s restic.Server, blob restic.Blob, path string) ([]f results := []findResult{} for _, node := range tree.Nodes { - debug(" testing entry %q\n", node.Name) + debug.Log("restic.find", " testing entry %q\n", node.Name) m, err := filepath.Match(c.pattern, node.Name) if err != nil { @@ -80,20 +81,20 @@ func (c CmdFind) findInTree(s restic.Server, blob restic.Blob, path string) ([]f } if m { - debug(" pattern matches\n") + debug.Log("restic.find", " pattern matches\n") if !c.oldest.IsZero() && node.ModTime.Before(c.oldest) { - debug(" ModTime is older than %s\n", c.oldest) + debug.Log("restic.find", " ModTime is older than %s\n", c.oldest) continue } if !c.newest.IsZero() && node.ModTime.After(c.newest) { - debug(" ModTime is newer than %s\n", c.newest) + debug.Log("restic.find", " ModTime is newer than %s\n", c.newest) continue } results = append(results, findResult{node: node, path: path}) } else { - debug(" pattern does not match\n") + debug.Log("restic.find", " pattern does not match\n") } if node.Type == "dir" { @@ -115,7 +116,7 @@ func (c CmdFind) findInTree(s restic.Server, blob restic.Blob, path string) ([]f } func (c CmdFind) findInSnapshot(s restic.Server, id backend.ID) error { - debug("searching in snapshot %s\n for entries within [%s %s]", id, c.oldest, c.newest) + debug.Log("restic.find", "searching in snapshot %s\n for entries within [%s %s]", id, c.oldest, c.newest) sn, err := restic.LoadSnapshot(s, id) if err != nil { diff --git a/cmd/restic/cmd_fsck.go b/cmd/restic/cmd_fsck.go index 64e34b726..ea65f9b1c 100644 --- a/cmd/restic/cmd_fsck.go +++ b/cmd/restic/cmd_fsck.go @@ -7,6 +7,7 @@ import ( "github.com/restic/restic" "github.com/restic/restic/backend" + "github.com/restic/restic/debug" ) type CmdFsck struct { @@ -34,7 +35,7 @@ func fsckFile(opts CmdFsck, s restic.Server, m *restic.Map, IDs []backend.ID) (u var bytes uint64 for _, id := range IDs { - debug("checking data blob %v\n", id) + debug.Log("restic.fsck", "checking data blob %v\n", id) // test if blob is in map blob, err := m.FindID(id) @@ -72,7 +73,7 @@ func fsckFile(opts CmdFsck, s restic.Server, m *restic.Map, IDs []backend.ID) (u } func fsckTree(opts CmdFsck, s restic.Server, blob restic.Blob) error { - debug("checking tree %v\n", blob.ID) + debug.Log("restic.fsck", "checking tree %v\n", blob.ID) tree, err := restic.LoadTree(s, blob) if err != nil { @@ -138,7 +139,7 @@ func fsckTree(opts CmdFsck, s restic.Server, blob restic.Blob) error { } func fsck_snapshot(opts CmdFsck, s restic.Server, id backend.ID) error { - debug("checking snapshot %v\n", id) + debug.Log("restic.fsck", "checking snapshot %v\n", id) sn, err := restic.LoadSnapshot(s, id) if err != nil { @@ -151,7 +152,7 @@ func fsck_snapshot(opts CmdFsck, s restic.Server, id backend.ID) error { err = fsckTree(opts, s, sn.Tree) if err != nil { - debug(" checking tree %v for snapshot %v\n", sn.Tree, id) + debug.Log("restic.fsck", " checking tree %v for snapshot %v\n", sn.Tree, id) fmt.Fprintf(os.Stderr, "snapshot %v:\n error for tree %v:\n %v\n", id, sn.Tree, err) } @@ -196,7 +197,7 @@ func (cmd CmdFsck) Execute(args []string) error { } list, err := s.List(backend.Snapshot) - debug("checking %d snapshots\n", len(list)) + debug.Log("restic.fsck", "checking %d snapshots\n", len(list)) if err != nil { return err } @@ -214,7 +215,7 @@ func (cmd CmdFsck) Execute(args []string) error { return firstErr } - debug("starting orphaned check\n") + debug.Log("restic.fsck", "starting orphaned check\n") l := []struct { desc string @@ -226,7 +227,7 @@ func (cmd CmdFsck) Execute(args []string) error { } for _, d := range l { - debug("checking for orphaned %v\n", d.desc) + debug.Log("restic.fsck", "checking for orphaned %v\n", d.desc) blobs, err := s.List(d.tpe) if err != nil { diff --git a/cmd/restic/cmd_version.go b/cmd/restic/cmd_version.go index d9fadbcc2..966c7b635 100644 --- a/cmd/restic/cmd_version.go +++ b/cmd/restic/cmd_version.go @@ -3,8 +3,6 @@ package main import ( "fmt" "runtime" - - "github.com/restic/restic" ) type CmdVersion struct{} @@ -20,13 +18,7 @@ func init() { } func (cmd CmdVersion) Execute(args []string) error { - fmt.Printf("restic version %s, lib %v on %v\n", version, restic.Version, runtime.Version()) - for _, s := range features { - fmt.Printf(" %s\n", s) - } - for _, s := range restic.Features { - fmt.Printf(" %s\n", s) - } + fmt.Printf("restic %s on %v\n", version, runtime.Version()) return nil } diff --git a/cmd/restic/debug.go b/cmd/restic/debug.go deleted file mode 100644 index bb3c18b60..000000000 --- a/cmd/restic/debug.go +++ /dev/null @@ -1,37 +0,0 @@ -// +build debug_cmd - -package main - -import ( - "fmt" - "io" - "log" - "os" - "path/filepath" - "time" -) - -var debugLogger = initDebugLogger() - -func initDebugLogger() *log.Logger { - // create new log file - filename := fmt.Sprintf("restic-debug-%d-%s", - os.Getpid(), time.Now().Format("20060201-150405")) - path := filepath.Join(os.TempDir(), filename) - f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0600) - if err != nil { - fmt.Fprintf(os.Stderr, "unable to create debug log file: %v", err) - os.Exit(2) - } - - // open logger - l := log.New(io.MultiWriter(os.Stderr, f), "DEBUG: ", log.LstdFlags) - fmt.Fprintf(os.Stderr, "debug log for restic command activated, writing log file %s\n", path) - l.Printf("restic %s", version) - - return l -} - -func debug(fmt string, args ...interface{}) { - debugLogger.Printf(fmt, args...) -} diff --git a/cmd/restic/debug_release.go b/cmd/restic/debug_release.go deleted file mode 100644 index ef42f0638..000000000 --- a/cmd/restic/debug_release.go +++ /dev/null @@ -1,5 +0,0 @@ -// +build !debug_cmd - -package main - -func debug(fmt string, args ...interface{}) {} diff --git a/cmd/restic/main.go b/cmd/restic/main.go index b413dcb41..a3028ce92 100644 --- a/cmd/restic/main.go +++ b/cmd/restic/main.go @@ -12,6 +12,7 @@ import ( "github.com/jessevdk/go-flags" "github.com/restic/restic" "github.com/restic/restic/backend" + "github.com/restic/restic/debug" ) var version = "compiled manually" @@ -166,6 +167,8 @@ func main() { // defer profile.Start(profile.MemProfileRate(100000), profile.ProfilePath(".")).Stop() opts.Repo = os.Getenv("RESTIC_REPOSITORY") + debug.Log("restic", "main %#v", os.Args) + _, err := parser.Parse() if e, ok := err.(*flags.Error); ok && e.Type == flags.ErrHelp { os.Exit(0) diff --git a/debug.go b/debug.go deleted file mode 100644 index d6dff581a..000000000 --- a/debug.go +++ /dev/null @@ -1,134 +0,0 @@ -// +build debug - -package restic - -import ( - "fmt" - "log" - "os" - "path" - "path/filepath" - "runtime" - "strings" - "syscall" - "time" -) - -var debugLogger = initDebugLogger() -var debugTags = make(map[string]bool) -var debugBreak = make(map[string]bool) - -func initDebugLogger() *log.Logger { - // create new log file - filename := fmt.Sprintf("restic-lib-debug-%d-%s", - os.Getpid(), time.Now().Format("20060201-150405")) - debugfile := filepath.Join(os.TempDir(), filename) - f, err := os.OpenFile(debugfile, os.O_WRONLY|os.O_CREATE, 0600) - if err != nil { - fmt.Fprintf(os.Stderr, "unable to create debug log file: %v", err) - os.Exit(2) - } - - // open logger - l := log.New(f, "DEBUG: ", log.LstdFlags) - fmt.Fprintf(os.Stderr, "debug log for restic library activated, writing log file %s\n", debugfile) - - // defaults - debugTags["break"] = true - - // initialize tags - env := os.Getenv("DEBUG_TAGS") - if len(env) > 0 { - tags := []string{} - - for _, tag := range strings.Split(env, ",") { - t := strings.TrimSpace(tag) - val := true - if t[0] == '-' { - val = false - t = t[1:] - } else if t[0] == '+' { - val = true - t = t[1:] - } - - // test pattern - _, err := path.Match(t, "") - if err != nil { - fmt.Fprintf(os.Stderr, "error: invalid pattern %q: %v\n", t, err) - os.Exit(5) - } - - debugTags[t] = val - tags = append(tags, tag) - } - - fmt.Fprintf(os.Stderr, "debug log enabled for: %v\n", tags) - } - - // initialize break tags - env = os.Getenv("DEBUG_BREAK") - if len(env) > 0 { - breaks := []string{} - - for _, tag := range strings.Split(env, ",") { - t := strings.TrimSpace(tag) - debugBreak[t] = true - breaks = append(breaks, t) - } - - fmt.Fprintf(os.Stderr, "debug breaks enabled for: %v\n", breaks) - } - - return l -} - -func debug(tag string, f string, args ...interface{}) { - dbgprint := func() { - fmt.Fprintf(os.Stderr, tag+": "+f, args...) - } - - debugLogger.Printf(f, args...) - - // check if tag is enabled directly - if v, ok := debugTags[tag]; ok { - if v { - dbgprint() - } - return - } - - // check for globbing - for k, v := range debugTags { - if m, _ := path.Match(k, tag); m { - if v { - dbgprint() - } - return - } - } - - // check if tag "all" is enabled - if v, ok := debugTags["all"]; ok && v { - dbgprint() - } -} - -func debug_break(tag string) { - // check if breaking is enabled - if v, ok := debugBreak[tag]; !ok || !v { - return - } - - _, file, line, _ := runtime.Caller(1) - debug("break", "stopping process %d at %s (%v:%v)\n", os.Getpid(), tag, file, line) - p, err := os.FindProcess(os.Getpid()) - if err != nil { - panic(err) - } - - err = p.Signal(syscall.SIGSTOP) - if err != nil { - panic(err) - } -} diff --git a/debug/debug.go b/debug/debug.go new file mode 100644 index 000000000..425cb5593 --- /dev/null +++ b/debug/debug.go @@ -0,0 +1,162 @@ +// +build debug + +package debug + +import ( + "fmt" + "log" + "os" + "path" + "runtime" + "strings" + "sync" + "syscall" +) + +var opts struct { + tags map[string]bool + breaks map[string]bool + m sync.Mutex +} + +var debugLogger = initDebugLogger() + +func initDebugLogger() (lgr *log.Logger) { + opts.tags = make(map[string]bool) + opts.breaks = make(map[string]bool) + + fmt.Fprintf(os.Stderr, "debug enabled\n") + + debugfile := os.Getenv("DEBUG_LOG") + if debugfile != "" { + fmt.Fprintf(os.Stderr, "debug log file %v\n", debugfile) + + // open logfile + f, err := os.OpenFile(debugfile, os.O_WRONLY|os.O_APPEND, 0600) + + if err != nil && os.IsNotExist(err) { + // create logfile + f, err = os.OpenFile(debugfile, os.O_WRONLY|os.O_CREATE, 0600) + } + + if err != nil { + fmt.Fprintf(os.Stderr, "unable to open debug log file: %v\n", err) + os.Exit(2) + } + + // seek to the end + _, err = f.Seek(2, 0) + if err != nil { + fmt.Fprintf(os.Stderr, "unable to seek to the end of %v: %v\n", debugfile, err) + os.Exit(3) + } + + // open logger + lgr = log.New(f, "", log.LstdFlags) + } + + // defaults + opts.tags["break"] = true + + // initialize tags + env := os.Getenv("DEBUG_TAGS") + if len(env) > 0 { + tags := []string{} + + for _, tag := range strings.Split(env, ",") { + t := strings.TrimSpace(tag) + val := true + if t[0] == '-' { + val = false + t = t[1:] + } else if t[0] == '+' { + val = true + t = t[1:] + } + + // test pattern + _, err := path.Match(t, "") + if err != nil { + fmt.Fprintf(os.Stderr, "error: invalid pattern %q: %v\n", t, err) + os.Exit(5) + } + + opts.tags[t] = val + tags = append(tags, tag) + } + + fmt.Fprintf(os.Stderr, "debug log enabled for: %v\n", tags) + } + + // initialize break tags + env = os.Getenv("DEBUG_BREAK") + if len(env) > 0 { + breaks := []string{} + + for _, tag := range strings.Split(env, ",") { + t := strings.TrimSpace(tag) + opts.breaks[t] = true + breaks = append(breaks, t) + } + + fmt.Fprintf(os.Stderr, "debug breaks enabled for: %v\n", breaks) + } + + return +} + +func Log(tag string, f string, args ...interface{}) { + // synchronize log writes + opts.m.Lock() + defer opts.m.Unlock() + + dbgprint := func() { + fmt.Fprintf(os.Stderr, "DEBUG["+tag+"]: "+f, args...) + } + + if debugLogger != nil { + debugLogger.Printf("["+tag+"] "+f, args...) + } + + // check if tag is enabled directly + if v, ok := opts.tags[tag]; ok { + if v { + dbgprint() + } + return + } + + // check for globbing + for k, v := range opts.tags { + if m, _ := path.Match(k, tag); m { + if v { + dbgprint() + } + return + } + } + + // check if tag "all" is enabled + if v, ok := opts.tags["all"]; ok && v { + dbgprint() + } +} + +func Break(tag string) { + // check if breaking is enabled + if v, ok := opts.breaks[tag]; !ok || !v { + return + } + + _, file, line, _ := runtime.Caller(1) + Log("break", "stopping process %d at %s (%v:%v)\n", os.Getpid(), tag, file, line) + p, err := os.FindProcess(os.Getpid()) + if err != nil { + panic(err) + } + + err = p.Signal(syscall.SIGSTOP) + if err != nil { + panic(err) + } +} diff --git a/debug/debug_release.go b/debug/debug_release.go new file mode 100644 index 000000000..c92bf1e67 --- /dev/null +++ b/debug/debug_release.go @@ -0,0 +1,7 @@ +// +build !debug + +package debug + +func Log(tag string, fmt string, args ...interface{}) {} + +func Break(string) {} diff --git a/debug_release.go b/debug_release.go deleted file mode 100644 index b49a2440b..000000000 --- a/debug_release.go +++ /dev/null @@ -1,7 +0,0 @@ -// +build !debug - -package restic - -func debug(tag string, fmt string, args ...interface{}) {} - -func debug_break(string) {} diff --git a/map.go b/map.go index 5e1566418..1a5b385c4 100644 --- a/map.go +++ b/map.go @@ -8,6 +8,7 @@ import ( "sync" "github.com/restic/restic/backend" + "github.com/restic/restic/debug" ) type Map struct { @@ -85,7 +86,7 @@ func (bl *Map) Insert(blob Blob) Blob { bl.m.Lock() defer bl.m.Unlock() - debug("Map.Insert", " Map<%p> insert %v", bl, blob) + debug.Log("Map.Insert", " Map<%p> insert %v", bl, blob) return bl.insert(blob) } diff --git a/test/run.sh b/test/run.sh index ba89f07ae..a4ae89070 100755 --- a/test/run.sh +++ b/test/run.sh @@ -97,6 +97,8 @@ done if [ -n "$failed" ]; then err "failed tests: ${failed}" - msg "bash version: $(bash --version)" + msg "restic versions:" + run restic version + run restic.debug version exit 1 fi diff --git a/tree.go b/tree.go index ea07b7d22..1fe6a9b01 100644 --- a/tree.go +++ b/tree.go @@ -14,6 +14,7 @@ import ( "github.com/juju/arrar" "github.com/restic/restic/backend" + "github.com/restic/restic/debug" ) type Tree struct { @@ -127,7 +128,7 @@ func LoadTreeRecursive(path string, s Server, blob Blob) (*Tree, error) { // CopyFrom recursively copies all content from other to t. func (t Tree) CopyFrom(other *Tree, s *Server) error { - debug("Tree.CopyFrom", "CopyFrom(%v)\n", other) + debug.Log("Tree.CopyFrom", "CopyFrom(%v)\n", other) for _, node := range t.Nodes { // only process files and dirs if node.Type != "file" && node.Type != "dir" { @@ -139,14 +140,14 @@ func (t Tree) CopyFrom(other *Tree, s *Server) error { // if the node could not be found or the type has changed, proceed to the next if err == ErrNodeNotFound || node.Type != oldNode.Type { - debug("Tree.CopyFrom", " node %v is new\n", node) + debug.Log("Tree.CopyFrom", " node %v is new\n", node) continue } if node.Type == "file" { // compare content if node.SameContent(oldNode) { - debug("Tree.CopyFrom", " file node %v has same content\n", node) + debug.Log("Tree.CopyFrom", " file node %v has same content\n", node) // check if all content is still available in the repository for _, id := range oldNode.Content { @@ -170,7 +171,7 @@ func (t Tree) CopyFrom(other *Tree, s *Server) error { return err } - debug("Tree.CopyFrom", " insert blob %v\n", blob) + debug.Log("Tree.CopyFrom", " insert blob %v\n", blob) t.Map.Insert(blob) } } @@ -183,7 +184,7 @@ func (t Tree) CopyFrom(other *Tree, s *Server) error { // check if tree has changed if node.tree.Equals(*oldNode.tree) { - debug("Tree.CopyFrom", " tree node %v has same content\n", node) + debug.Log("Tree.CopyFrom", " tree node %v has same content\n", node) // if nothing has changed, copy subtree ID node.Subtree = oldNode.Subtree @@ -194,12 +195,12 @@ func (t Tree) CopyFrom(other *Tree, s *Server) error { return err } - debug("Tree.CopyFrom", " insert blob %v\n", blob) + debug.Log("Tree.CopyFrom", " insert blob %v\n", blob) t.Map.Insert(blob) } else { - debug("Tree.CopyFrom", " trees are not equal: %v\n", node) - debug("Tree.CopyFrom", " %#v\n", node.tree) - debug("Tree.CopyFrom", " %#v\n", oldNode.tree) + debug.Log("Tree.CopyFrom", " trees are not equal: %v\n", node) + debug.Log("Tree.CopyFrom", " %#v\n", node.tree) + debug.Log("Tree.CopyFrom", " %#v\n", oldNode.tree) } } } @@ -210,20 +211,20 @@ func (t Tree) CopyFrom(other *Tree, s *Server) error { // Equals returns true if t and other have exactly the same nodes and map. func (t Tree) Equals(other Tree) bool { if len(t.Nodes) != len(other.Nodes) { - debug("Tree.Equals", "tree.Equals(): trees have different number of nodes") + debug.Log("Tree.Equals", "tree.Equals(): trees have different number of nodes") return false } if !t.Map.Equals(other.Map) { - debug("Tree.Equals", "tree.Equals(): maps aren't equal") + debug.Log("Tree.Equals", "tree.Equals(): maps aren't equal") return false } for i := 0; i < len(t.Nodes); i++ { if !t.Nodes[i].Equals(*other.Nodes[i]) { - debug("Tree.Equals", "tree.Equals(): node %d is different:", i) - debug("Tree.Equals", " %#v", t.Nodes[i]) - debug("Tree.Equals", " %#v", other.Nodes[i]) + debug.Log("Tree.Equals", "tree.Equals(): node %d is different:", i) + debug.Log("Tree.Equals", " %#v", t.Nodes[i]) + debug.Log("Tree.Equals", " %#v", other.Nodes[i]) return false } } diff --git a/version.go b/version.go deleted file mode 100644 index a8f729d33..000000000 --- a/version.go +++ /dev/null @@ -1,4 +0,0 @@ -package restic - -var Version = "compiled manually" -var Features = []string{}