diff --git a/internal/archiver/archiver.go b/internal/archiver/archiver.go index 2fd170a3a..bc74bd75f 100644 --- a/internal/archiver/archiver.go +++ b/internal/archiver/archiver.go @@ -548,13 +548,7 @@ func (arch *Archiver) SaveTree(ctx context.Context, snPath string, atree *Tree, futureNodes := make(map[string]FutureNode) // iterate over the nodes of atree in lexicographic (=deterministic) order - names := make([]string, 0, len(atree.Nodes)) - for name := range atree.Nodes { - names = append(names, name) - } - sort.Strings(names) - - for _, name := range names { + for _, name := range atree.NodeNames() { subatree := atree.Nodes[name] // test if context has been cancelled @@ -563,7 +557,7 @@ func (arch *Archiver) SaveTree(ctx context.Context, snPath string, atree *Tree, } // this is a leaf node - if subatree.Path != "" { + if subatree.Leaf() { fn, excluded, err := arch.Save(ctx, join(snPath, name), subatree.Path, previous.Find(name)) if err != nil { diff --git a/internal/archiver/tree.go b/internal/archiver/tree.go index 04c0a8e33..16a78ee70 100644 --- a/internal/archiver/tree.go +++ b/internal/archiver/tree.go @@ -2,6 +2,7 @@ package archiver import ( "fmt" + "sort" "github.com/restic/restic/internal/debug" "github.com/restic/restic/internal/errors" @@ -199,6 +200,24 @@ func (t Tree) String() string { return formatTree(t, "") } +// Leaf returns true if this is a leaf node, which means Path is set to a +// non-empty string and the contents of Path should be inserted at this point +// in the tree. +func (t Tree) Leaf() bool { + return t.Path != "" +} + +// NodeNames returns the sorted list of subtree names. +func (t Tree) NodeNames() []string { + // iterate over the nodes of atree in lexicographic (=deterministic) order + names := make([]string, 0, len(t.Nodes)) + for name := range t.Nodes { + names = append(names, name) + } + sort.Strings(names) + return names +} + // formatTree returns a text representation of the tree t. func formatTree(t Tree, indent string) (s string) { for name, node := range t.Nodes {