diff options
author | Jeremy Stribling <strib@alum.mit.edu> | 2017-08-25 13:52:07 -0700 |
---|---|---|
committer | Jeremy Stribling <strib@alum.mit.edu> | 2017-08-27 17:14:49 -0700 |
commit | d68f45f8aaca461167907c07e8c161be14e87157 (patch) | |
tree | 1fecddbe0c384ab077e5588321362a672f0e9fc4 /plumbing/object/tree.go | |
parent | 631a45f55b397090ad7d817a3c72041cfc3729f3 (diff) | |
download | go-git-d68f45f8aaca461167907c07e8c161be14e87157.tar.gz |
plumbing: use `seen` map in tree walker
This helps avoids iterating down the same trees for every commit. For
a big-ish repo with 35K objects (17K commits), this reduced the time
for calling `revlist.Objects` during a push (with 0 hashes to ignore)
from more than ten minutes to less than a minute.
Diffstat (limited to 'plumbing/object/tree.go')
-rw-r--r-- | plumbing/object/tree.go | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/plumbing/object/tree.go b/plumbing/object/tree.go index 512db9f..44ac720 100644 --- a/plumbing/object/tree.go +++ b/plumbing/object/tree.go @@ -297,9 +297,10 @@ func (iter *treeEntryIter) Next() (TreeEntry, error) { // TreeWalker provides a means of walking through all of the entries in a Tree. type TreeWalker struct { - stack []treeEntryIter + stack []*treeEntryIter base string recursive bool + seen map[plumbing.Hash]bool s storer.EncodedObjectStorer t *Tree @@ -309,13 +310,14 @@ type TreeWalker struct { // // It is the caller's responsibility to call Close() when finished with the // tree walker. -func NewTreeWalker(t *Tree, recursive bool) *TreeWalker { - stack := make([]treeEntryIter, 0, startingStackSize) - stack = append(stack, treeEntryIter{t, 0}) +func NewTreeWalker(t *Tree, recursive bool, seen map[plumbing.Hash]bool) *TreeWalker { + stack := make([]*treeEntryIter, 0, startingStackSize) + stack = append(stack, &treeEntryIter{t, 0}) return &TreeWalker{ stack: stack, recursive: recursive, + seen: seen, s: t.s, t: t, @@ -358,6 +360,10 @@ func (w *TreeWalker) Next() (name string, entry TreeEntry, err error) { return } + if w.seen[entry.Hash] { + continue + } + if entry.Mode == filemode.Dir { obj, err = GetTree(w.s, entry.Hash) } @@ -377,7 +383,7 @@ func (w *TreeWalker) Next() (name string, entry TreeEntry, err error) { } if t, ok := obj.(*Tree); ok { - w.stack = append(w.stack, treeEntryIter{t, 0}) + w.stack = append(w.stack, &treeEntryIter{t, 0}) w.base = path.Join(w.base, entry.Name) } |