Skip to content

Commit b83cd2d

Browse files
committed
plumbing: object, adds tree path cache to trees. Fixes src-d#794
The cache is used in Tree.FindEntry for faster path search. Signed-off-by: Javi Fontan <[email protected]>
1 parent 73c775e commit b83cd2d

File tree

1 file changed

+26
-1
lines changed

1 file changed

+26
-1
lines changed

plumbing/object/tree.go

+26-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"io"
88
"path"
9+
"path/filepath"
910
"strings"
1011

1112
"gopkg.in/src-d/go-git.v4/plumbing"
@@ -34,6 +35,7 @@ type Tree struct {
3435

3536
s storer.EncodedObjectStorer
3637
m map[string]*TreeEntry
38+
t map[string]*Tree // tree path cache
3739
}
3840

3941
// GetTree gets a tree from an object storer and decodes it.
@@ -111,14 +113,37 @@ func (t *Tree) TreeEntryFile(e *TreeEntry) (*File, error) {
111113

112114
// FindEntry search a TreeEntry in this tree or any subtree.
113115
func (t *Tree) FindEntry(path string) (*TreeEntry, error) {
116+
if t.t == nil {
117+
t.t = make(map[string]*Tree)
118+
}
119+
114120
pathParts := strings.Split(path, "/")
121+
startingTree := t
122+
pathCurrent := ""
123+
124+
// search for the longest path in the tree path cache
125+
for i := len(pathParts); i > 1; i-- {
126+
path := filepath.Join(pathParts[:i]...)
127+
128+
tree, ok := t.t[path]
129+
if ok {
130+
startingTree = tree
131+
pathParts = pathParts[i:]
132+
pathCurrent = path
133+
134+
break
135+
}
136+
}
115137

116138
var tree *Tree
117139
var err error
118-
for tree = t; len(pathParts) > 1; pathParts = pathParts[1:] {
140+
for tree = startingTree; len(pathParts) > 1; pathParts = pathParts[1:] {
119141
if tree, err = tree.dir(pathParts[0]); err != nil {
120142
return nil, err
121143
}
144+
145+
pathCurrent = filepath.Join(pathCurrent, pathParts[0])
146+
t.t[pathCurrent] = tree
122147
}
123148

124149
return tree.entry(pathParts[0])

0 commit comments

Comments
 (0)