aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoshua Sjoding <joshua.sjoding@scjalliance.com>2016-02-17 12:01:02 -0800
committerJoshua Sjoding <joshua.sjoding@scjalliance.com>2016-02-17 12:01:02 -0800
commita72c4ec54bb0502bd230dd007ebd1ef7b381afc7 (patch)
tree0cc85b4632818b7e9dd72d27a10698843304837b
parent9df17e545a445f58c5c43a1ece49bf1ff09e3b02 (diff)
downloadgo-git-a72c4ec54bb0502bd230dd007ebd1ef7b381afc7.tar.gz
Tree.Entries is now a slice
Tree's mapping of names to entries has been made internal, and will only be built when necessary with the first call to Tree.File().
-rw-r--r--objects_test.go9
-rw-r--r--tree.go41
2 files changed, 27 insertions, 23 deletions
diff --git a/objects_test.go b/objects_test.go
index eadf65a..4745774 100644
--- a/objects_test.go
+++ b/objects_test.go
@@ -54,9 +54,12 @@ func (s *ObjectsSuite) TestParseTree(c *C) {
c.Assert(err, IsNil)
c.Assert(tree.Entries, HasLen, 8)
- c.Assert(tree.Entries[".gitignore"].Name, Equals, ".gitignore")
- c.Assert(tree.Entries[".gitignore"].Mode.String(), Equals, "-rw-r--r--")
- c.Assert(tree.Entries[".gitignore"].Hash.String(), Equals, "32858aad3c383ed1ff0a0f9bdf231d54a00c9e88")
+
+ tree.buildMap()
+ c.Assert(tree.m, HasLen, 8)
+ c.Assert(tree.m[".gitignore"].Name, Equals, ".gitignore")
+ c.Assert(tree.m[".gitignore"].Mode.String(), Equals, "-rw-r--r--")
+ c.Assert(tree.m[".gitignore"].Hash.String(), Equals, "32858aad3c383ed1ff0a0f9bdf231d54a00c9e88")
count := 0
iter := tree.Files()
diff --git a/tree.go b/tree.go
index 9a750e0..16dc3e1 100644
--- a/tree.go
+++ b/tree.go
@@ -24,11 +24,11 @@ var (
// Tree is basically like a directory - it references a bunch of other trees
// and/or blobs (i.e. files and sub-directories)
type Tree struct {
- Entries map[string]TreeEntry
- OrderedNames []string
- Hash core.Hash
+ Entries []TreeEntry
+ Hash core.Hash
r *Repository
+ m map[string]*TreeEntry
}
// TreeEntry represents a file
@@ -112,12 +112,15 @@ func (t *Tree) dir(baseName string) (*Tree, error) {
var errEntryNotFound = errors.New("entry not found")
func (t *Tree) entry(baseName string) (*TreeEntry, error) {
- entry, ok := t.Entries[baseName]
+ if t.m == nil {
+ t.buildMap()
+ }
+ entry, ok := t.m[baseName]
if !ok {
return nil, errEntryNotFound
}
- return &entry, nil
+ return entry, nil
}
func (t *Tree) Files() *FileIter {
@@ -135,7 +138,8 @@ func (t *Tree) Decode(o core.Object) error {
return nil
}
- t.Entries = make(map[string]TreeEntry)
+ t.Entries = nil
+ t.m = nil
r := bufio.NewReader(o.Reader())
for {
@@ -165,17 +169,23 @@ func (t *Tree) Decode(o core.Object) error {
}
baseName := name[:len(name)-1]
- t.Entries[baseName] = TreeEntry{
+ t.Entries = append(t.Entries, TreeEntry{
Hash: hash,
Mode: os.FileMode(fm),
Name: baseName,
- }
- t.OrderedNames = append(t.OrderedNames, baseName)
+ })
}
return nil
}
+func (t *Tree) buildMap() {
+ t.m = make(map[string]*TreeEntry)
+ for i := 0; i < len(t.Entries); i++ {
+ t.m[t.Entries[i].Name] = &t.Entries[i]
+ }
+}
+
// TreeEntryIter facilitates iterating through the TreeEntry objects in a Tree.
type TreeEntryIter struct {
t *Tree
@@ -187,20 +197,11 @@ func NewTreeEntryIter(t *Tree) *TreeEntryIter {
}
func (iter *TreeEntryIter) Next() (TreeEntry, error) {
- if iter.pos >= len(iter.t.OrderedNames) {
+ if iter.pos >= len(iter.t.Entries) {
return TreeEntry{}, io.EOF
}
-
- entry, ok := iter.t.Entries[iter.t.OrderedNames[iter.pos]]
- if !ok {
- // Probable race condition or internal bug
- // FIXME: Report more severe error or panic
- return TreeEntry{}, io.EOF
- }
-
iter.pos++
-
- return entry, nil
+ return iter.t.Entries[iter.pos-1], nil
}
// TreeEntryIter facilitates iterating through the descendent subtrees of a