Skip to content

Commit 0b6dbfb

Browse files
committed
Avoid nearly all external 'git' invocations when doing directory listing (.editorconfig code path is still hit).
Signed-off-by: Filip Navara <[email protected]>
1 parent 89af3ab commit 0b6dbfb

File tree

6 files changed

+68
-140
lines changed

6 files changed

+68
-140
lines changed

modules/git/commit_info.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,18 @@ func convertCommit(c *object.Commit) *Commit {
5555
}
5656
}
5757

58+
parents := make([]SHA1, len(c.ParentHashes))
59+
for i, parentHash := range c.ParentHashes {
60+
parents[i] = SHA1(parentHash)
61+
}
62+
5863
return &Commit{
5964
ID: SHA1(c.Hash),
6065
CommitMessage: c.Message,
6166
Committer: &commiter,
6267
Author: &author,
6368
Signature: pgpSignaure,
69+
parents: parents,
6470
}
6571
}
6672

modules/git/repo.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ import (
2727
type Repository struct {
2828
Path string
2929

30-
commitCache *ObjectCache
31-
tagCache *ObjectCache
30+
tagCache *ObjectCache
3231

3332
gogitRepo *gogit.Repository
3433
gogitStorage *filesystem.Storage
@@ -96,7 +95,6 @@ func OpenRepository(repoPath string) (*Repository, error) {
9695
Path: repoPath,
9796
gogitRepo: gogitRepo,
9897
gogitStorage: storage,
99-
commitCache: newObjectCache(),
10098
tagCache: newObjectCache(),
10199
}, nil
102100
}

modules/git/repo_branch.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"fmt"
1010
"strings"
1111

12-
"gopkg.in/src-d/go-git.v4"
1312
"gopkg.in/src-d/go-git.v4/plumbing"
1413
)
1514

@@ -29,7 +28,11 @@ func IsBranchExist(repoPath, name string) bool {
2928

3029
// IsBranchExist returns true if given branch exists in current repository.
3130
func (repo *Repository) IsBranchExist(name string) bool {
32-
return IsBranchExist(repo.Path, name)
31+
_, err := repo.gogitRepo.Reference(plumbing.ReferenceName(BranchPrefix+name), true)
32+
if err != nil {
33+
return false
34+
}
35+
return true
3336
}
3437

3538
// Branch represents a Git branch.
@@ -64,24 +67,21 @@ func (repo *Repository) SetDefaultBranch(name string) error {
6467

6568
// GetBranches returns all branches of the repository.
6669
func (repo *Repository) GetBranches() ([]string, error) {
67-
r, err := git.PlainOpen(repo.Path)
68-
if err != nil {
69-
return nil, err
70-
}
70+
var branchNames []string
7171

72-
branchIter, err := r.Branches()
72+
branches, err := repo.gogitRepo.Branches()
7373
if err != nil {
7474
return nil, err
7575
}
76-
branches := make([]string, 0)
77-
if err = branchIter.ForEach(func(branch *plumbing.Reference) error {
78-
branches = append(branches, branch.Name().Short())
76+
77+
branches.ForEach(func(branch *plumbing.Reference) error {
78+
branchNames = append(branchNames, strings.TrimPrefix(branch.Name().String(), BranchPrefix))
7979
return nil
80-
}); err != nil {
81-
return nil, err
82-
}
80+
})
81+
82+
// TODO: Sort?
8383

84-
return branches, nil
84+
return branchNames, nil
8585
}
8686

8787
// DeleteBranchOptions Option(s) for delete branch

modules/git/repo_commit.go

Lines changed: 20 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,19 @@ import (
1010
"strconv"
1111
"strings"
1212

13-
version "github.com/mcuadros/go-version"
13+
"github.com/mcuadros/go-version"
14+
15+
"gopkg.in/src-d/go-git.v4/plumbing"
1416
)
1517

1618
// GetRefCommitID returns the last commit ID string of given reference (branch or tag).
1719
func (repo *Repository) GetRefCommitID(name string) (string, error) {
18-
stdout, err := NewCommand("show-ref", "--verify", name).RunInDir(repo.Path)
20+
ref, err := repo.gogitRepo.Reference(plumbing.ReferenceName(name), true)
1921
if err != nil {
20-
if strings.Contains(err.Error(), "not a valid ref") {
21-
return "", ErrNotExist{name, ""}
22-
}
2322
return "", err
2423
}
25-
return strings.Split(stdout, " ")[0], nil
24+
25+
return ref.Hash().String(), nil
2626
}
2727

2828
// GetBranchCommitID returns last commit ID string of given branch.
@@ -42,114 +42,35 @@ func (repo *Repository) GetTagCommitID(name string) (string, error) {
4242
return strings.TrimSpace(stdout), nil
4343
}
4444

45-
// parseCommitData parses commit information from the (uncompressed) raw
46-
// data from the commit object.
47-
// \n\n separate headers from message
48-
func parseCommitData(data []byte) (*Commit, error) {
49-
commit := new(Commit)
50-
commit.parents = make([]SHA1, 0, 1)
51-
// we now have the contents of the commit object. Let's investigate...
52-
nextline := 0
53-
l:
54-
for {
55-
eol := bytes.IndexByte(data[nextline:], '\n')
56-
switch {
57-
case eol > 0:
58-
line := data[nextline : nextline+eol]
59-
spacepos := bytes.IndexByte(line, ' ')
60-
reftype := line[:spacepos]
61-
switch string(reftype) {
62-
case "tree", "object":
63-
id, err := NewIDFromString(string(line[spacepos+1:]))
64-
if err != nil {
65-
return nil, err
66-
}
67-
commit.Tree.ID = id
68-
case "parent":
69-
// A commit can have one or more parents
70-
oid, err := NewIDFromString(string(line[spacepos+1:]))
71-
if err != nil {
72-
return nil, err
73-
}
74-
commit.parents = append(commit.parents, oid)
75-
case "author", "tagger":
76-
sig, err := newSignatureFromCommitline(line[spacepos+1:])
77-
if err != nil {
78-
return nil, err
79-
}
80-
commit.Author = sig
81-
case "committer":
82-
sig, err := newSignatureFromCommitline(line[spacepos+1:])
83-
if err != nil {
84-
return nil, err
85-
}
86-
commit.Committer = sig
87-
case "gpgsig":
88-
sig, err := newGPGSignatureFromCommitline(data, nextline+spacepos+1, false)
89-
if err != nil {
90-
return nil, err
91-
}
92-
commit.Signature = sig
93-
}
94-
nextline += eol + 1
95-
case eol == 0:
96-
cm := string(data[nextline+1:])
97-
98-
// Tag GPG signatures are stored below the commit message
99-
sigindex := strings.Index(cm, "-----BEGIN PGP SIGNATURE-----")
100-
if sigindex != -1 {
101-
sig, err := newGPGSignatureFromCommitline(data, (nextline+1)+sigindex, true)
102-
if err == nil && sig != nil {
103-
// remove signature from commit message
104-
if sigindex == 0 {
105-
cm = ""
106-
} else {
107-
cm = cm[:sigindex-1]
108-
}
109-
commit.Signature = sig
110-
}
111-
}
112-
113-
commit.CommitMessage = cm
114-
break l
115-
default:
116-
break l
117-
}
118-
}
119-
return commit, nil
120-
}
121-
12245
func (repo *Repository) getCommit(id SHA1) (*Commit, error) {
123-
c, ok := repo.commitCache.Get(id.String())
124-
if ok {
125-
log("Hit cache: %s", id)
126-
return c.(*Commit), nil
127-
}
46+
//c, ok := repo.commitCache.Get(id.String())
47+
//if ok {
48+
// log("Hit cache: %s", id)
49+
// return c.(*Commit), nil
50+
//}
12851

129-
data, err := NewCommand("cat-file", "-p", id.String()).RunInDirBytes(repo.Path)
52+
gogitCommit, err := repo.gogitRepo.CommitObject(plumbing.Hash(id))
13053
if err != nil {
131-
if strings.Contains(err.Error(), "fatal: Not a valid object name") {
132-
return nil, ErrNotExist{id.String(), ""}
133-
}
13454
return nil, err
13555
}
13656

137-
commit, err := parseCommitData(data)
138-
if err != nil {
139-
return nil, err
140-
}
57+
commit := convertCommit(gogitCommit)
14158
commit.repo = repo
142-
commit.ID = id
14359

144-
data, err = NewCommand("name-rev", id.String()).RunInDirBytes(repo.Path)
60+
if tree, err := gogitCommit.Tree(); err != nil {
61+
commit.Tree.ID = SHA1(tree.Hash)
62+
commit.Tree.gogitTree = tree
63+
}
64+
65+
data, err := NewCommand("name-rev", id.String()).RunInDirBytes(repo.Path)
14566
if err != nil {
14667
return nil, err
14768
}
14869

14970
// name-rev commitID output will be "COMMIT_ID master" or "COMMIT_ID master~12"
15071
commit.Branch = strings.Split(strings.Split(string(data), " ")[1], "~")[0]
72+
//repo.commitCache.Set(id.String(), commit)
15173

152-
repo.commitCache.Set(id.String(), commit)
15374
return commit, nil
15475
}
15576

modules/git/repo_tag.go

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"strings"
99

1010
"github.com/mcuadros/go-version"
11+
"gopkg.in/src-d/go-git.v4/plumbing"
1112
)
1213

1314
// TagPrefix tags prefix path on the repository
@@ -20,7 +21,11 @@ func IsTagExist(repoPath, name string) bool {
2021

2122
// IsTagExist returns true if given tag exists in the repository.
2223
func (repo *Repository) IsTagExist(name string) bool {
23-
return IsTagExist(repo.Path, name)
24+
_, err := repo.gogitRepo.Reference(plumbing.ReferenceName(TagPrefix+name), true)
25+
if err != nil {
26+
return false
27+
}
28+
return true
2429
}
2530

2631
// CreateTag create one tag in the repository
@@ -122,28 +127,25 @@ func (repo *Repository) GetTagInfos() ([]*Tag, error) {
122127

123128
// GetTags returns all tags of the repository.
124129
func (repo *Repository) GetTags() ([]string, error) {
125-
cmd := NewCommand("tag", "-l")
126-
if version.Compare(gitVersion, "2.0.0", ">=") {
127-
cmd.AddArguments("--sort=-v:refname")
128-
}
130+
var tagNames []string
129131

130-
stdout, err := cmd.RunInDir(repo.Path)
132+
tags, err := repo.gogitRepo.Tags()
131133
if err != nil {
132-
return nil, err
134+
return nil, nil
133135
}
134136

135-
tags := strings.Split(stdout, "\n")
136-
tags = tags[:len(tags)-1]
137+
tags.ForEach(func(tag *plumbing.Reference) error {
138+
tagNames = append(tagNames, strings.TrimPrefix(tag.Name().String(), TagPrefix))
139+
return nil
140+
})
137141

138-
if version.Compare(gitVersion, "2.0.0", "<") {
139-
version.Sort(tags)
142+
version.Sort(tagNames)
140143

141-
// Reverse order
142-
for i := 0; i < len(tags)/2; i++ {
143-
j := len(tags) - i - 1
144-
tags[i], tags[j] = tags[j], tags[i]
145-
}
144+
// Reverse order
145+
for i := 0; i < len(tagNames)/2; i++ {
146+
j := len(tagNames) - i - 1
147+
tagNames[i], tagNames[j] = tagNames[j], tagNames[i]
146148
}
147149

148-
return tags, nil
150+
return tagNames, nil
149151
}

modules/git/repo_tree.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,17 @@
44

55
package git
66

7+
import "gopkg.in/src-d/go-git.v4/plumbing"
8+
79
func (repo *Repository) getTree(id SHA1) (*Tree, error) {
8-
treePath := filepathFromSHA1(repo.Path, id.String())
9-
if isFile(treePath) {
10-
_, err := NewCommand("ls-tree", id.String()).RunInDir(repo.Path)
11-
if err != nil {
12-
return nil, ErrNotExist{id.String(), ""}
13-
}
10+
gogitTree, err := repo.gogitRepo.TreeObject(plumbing.Hash(id))
11+
if err != nil {
12+
return nil, err
1413
}
1514

16-
return NewTree(repo, id), nil
15+
tree := NewTree(repo, id)
16+
tree.gogitTree = gogitTree
17+
return tree, nil
1718
}
1819

1920
// GetTree find the tree object in the repository.

0 commit comments

Comments
 (0)