Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Latest commit

 

History

History
History
155 lines (131 loc) · 4.84 KB

File metadata and controls

155 lines (131 loc) · 4.84 KB
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package codenav
import (
"context"
"fmt"
"strings"
"sync"
"github.com/sourcegraph/sourcegraph/internal/codeintel/codenav/shared"
"github.com/sourcegraph/sourcegraph/internal/codeintel/shared/gitserver"
"github.com/sourcegraph/sourcegraph/lib/errors"
)
type CommitCache interface {
AreCommitsResolvable(ctx context.Context, commits []gitserver.RepositoryCommit) ([]bool, error)
ExistsBatch(ctx context.Context, commits []gitserver.RepositoryCommit) ([]bool, error)
SetResolvableCommit(repositoryID int, commit string)
}
type commitCache struct {
gitserverClient shared.GitserverClient
mutex sync.RWMutex
cache map[int]map[string]bool
}
func NewCommitCache(client shared.GitserverClient) CommitCache {
return &commitCache{
gitserverClient: client,
cache: map[int]map[string]bool{},
}
}
// ExistsBatch determines if the given commits are resolvable for the given repositories.
// If we do not know the answer from a previous call to set or existsBatch, we ask gitserver
// to resolve the remaining commits and store the results for subsequent calls. This method
// returns a slice of the same size as the input slice, true indicating that the commit at
// the symmetric index exists.
func (c *commitCache) ExistsBatch(ctx context.Context, commits []gitserver.RepositoryCommit) ([]bool, error) {
exists := make([]bool, len(commits))
rcIndexMap := make([]int, 0, len(commits))
rcs := make([]gitserver.RepositoryCommit, 0, len(commits))
for i, rc := range commits {
if e, ok := c.getInternal(rc.RepositoryID, rc.Commit); ok {
exists[i] = e
} else {
rcIndexMap = append(rcIndexMap, i)
rcs = append(rcs, gitserver.RepositoryCommit{
RepositoryID: rc.RepositoryID,
Commit: rc.Commit,
})
}
}
if len(rcs) == 0 {
return exists, nil
}
// Perform heavy work outside of critical section
e, err := c.gitserverClient.CommitsExist(ctx, rcs)
if err != nil {
return nil, errors.Wrap(err, "gitserverClient.CommitsExist")
}
if len(e) != len(rcs) {
panic(strings.Join([]string{
fmt.Sprintf("Expected slice returned from CommitsExist to have len %d, but has len %d.", len(rcs), len(e)),
"If this panic occurred during a test, your test is missing a mock definition for CommitsExist.",
"If this is occurred during runtime, please file a bug.",
}, " "))
}
for i, rc := range rcs {
exists[rcIndexMap[i]] = e[i]
c.setInternal(rc.RepositoryID, rc.Commit, e[i])
}
return exists, nil
}
// AreCommitsResolvable determines if the given commits are resolvable for the given repositories.
// If we do not know the answer from a previous call to set or AreCommitsResolvable, we ask gitserver
// to resolve the remaining commits and store the results for subsequent calls. This method
// returns a slice of the same size as the input slice, true indicating that the commit at
// the symmetric index exists.
func (c *commitCache) AreCommitsResolvable(ctx context.Context, commits []gitserver.RepositoryCommit) ([]bool, error) {
exists := make([]bool, len(commits))
rcIndexMap := make([]int, 0, len(commits))
rcs := make([]gitserver.RepositoryCommit, 0, len(commits))
for i, rc := range commits {
if e, ok := c.getInternal(rc.RepositoryID, rc.Commit); ok {
exists[i] = e
} else {
rcIndexMap = append(rcIndexMap, i)
rcs = append(rcs, gitserver.RepositoryCommit{
RepositoryID: rc.RepositoryID,
Commit: rc.Commit,
})
}
}
// if there are no repository commits to fetch, we're done
if len(rcs) == 0 {
return exists, nil
}
// Perform heavy work outside of critical section
e, err := c.gitserverClient.CommitsExist(ctx, rcs)
if err != nil {
return nil, errors.Wrap(err, "gitserverClient.CommitsExist")
}
if len(e) != len(rcs) {
panic(strings.Join([]string{
fmt.Sprintf("Expected slice returned from CommitsExist to have len %d, but has len %d.", len(rcs), len(e)),
"If this panic occurred during a test, your test is missing a mock definition for CommitsExist.",
"If this is occurred during runtime, please file a bug.",
}, " "))
}
for i, rc := range rcs {
exists[rcIndexMap[i]] = e[i]
c.setInternal(rc.RepositoryID, rc.Commit, e[i])
}
return exists, nil
}
// set marks the given repository and commit as valid and resolvable by gitserver.
func (c *commitCache) SetResolvableCommit(repositoryID int, commit string) {
c.setInternal(repositoryID, commit, true)
}
func (c *commitCache) getInternal(repositoryID int, commit string) (bool, bool) {
c.mutex.RLock()
defer c.mutex.RUnlock()
if repositoryMap, ok := c.cache[repositoryID]; ok {
if exists, ok := repositoryMap[commit]; ok {
return exists, true
}
}
return false, false
}
func (c *commitCache) setInternal(repositoryID int, commit string, exists bool) {
c.mutex.Lock()
defer c.mutex.Unlock()
if _, ok := c.cache[repositoryID]; !ok {
c.cache[repositoryID] = map[string]bool{}
}
c.cache[repositoryID][commit] = exists
}
Morty Proxy This is a proxified and sanitized view of the page, visit original site.