@@ -2,16 +2,16 @@ package backend
22
33import (
44 "context"
5+ "net/url"
56 "strings"
67
7- "github.com/sourcegraph/sourcegraph/cmd/frontend/envvar"
88 log15 "gopkg.in/inconshreveable/log15.v2"
99
1010 "github.com/pkg/errors"
11-
11+ "github.com/sourcegraph/sourcegraph/cmd/frontend/db"
12+ "github.com/sourcegraph/sourcegraph/cmd/frontend/envvar"
1213 "github.com/sourcegraph/sourcegraph/cmd/frontend/types"
1314 "github.com/sourcegraph/sourcegraph/pkg/api"
14- "github.com/sourcegraph/sourcegraph/pkg/conf"
1515 "github.com/sourcegraph/sourcegraph/pkg/gitserver"
1616 "github.com/sourcegraph/sourcegraph/pkg/repoupdater"
1717 "github.com/sourcegraph/sourcegraph/pkg/repoupdater/protocol"
@@ -22,17 +22,25 @@ import (
2222// knowing the remote URL is necessary to perform any operations (from method calls on the return
2323// value), those operations will fail. This occurs when the repository isn't cloned on gitserver or
2424// when an update is needed (eg in ResolveRevision).
25- func CachedGitRepo (repo * types.Repo ) gitserver.Repo {
26- if r := quickGitserverRepo (repo .Name ); r != nil {
27- return * r
25+ func CachedGitRepo (ctx context.Context , repo * types.Repo ) (* gitserver.Repo , error ) {
26+ r , err := quickGitserverRepo (ctx , repo .Name )
27+ if err != nil {
28+ return nil , err
29+ }
30+ if r != nil {
31+ return r , nil
2832 }
29- return gitserver.Repo {Name : repo .Name }
33+ return & gitserver.Repo {Name : repo .Name }, nil
3034}
3135
3236// GitRepo returns a handle to the Git repository with the up-to-date (as of the time of this call)
3337// remote URL. See CachedGitRepo for when this is necessary vs. unnecessary.
3438func GitRepo (ctx context.Context , repo * types.Repo ) (gitserver.Repo , error ) {
35- if gitserverRepo := quickGitserverRepo (repo .Name ); gitserverRepo != nil {
39+ gitserverRepo , err := quickGitserverRepo (ctx , repo .Name )
40+ if err != nil {
41+ return gitserver.Repo {Name : repo .Name }, err
42+ }
43+ if gitserverRepo != nil {
3644 return * gitserverRepo , nil
3745 }
3846
@@ -49,27 +57,79 @@ func GitRepo(ctx context.Context, repo *types.Repo) (gitserver.Repo, error) {
4957 return gitserver.Repo {Name : result .Repo .Name , URL : result .Repo .VCS .URL }, nil
5058}
5159
52- func quickGitserverRepo (repo api.RepoName ) * gitserver.Repo {
60+ func quickGitserverRepo (ctx context. Context , repo api.RepoName ) ( * gitserver.Repo , error ) {
5361 // If it is possible to 100% correctly determine it statically, use a fast path. This is
5462 // used to avoid a RepoLookup call for public GitHub.com and GitLab.com repositories
5563 // (especially on Sourcegraph.com), which reduces rate limit pressure significantly.
5664 //
5765 // This fails for private repositories, which require authentication in the URL userinfo.
5866
67+ lowerRepo := strings .ToLower (string (repo ))
68+ var hasToken func (context.Context ) (bool , error )
5969 switch {
60- case strings .HasPrefix (strings .ToLower (string (repo )), "github.com/" ):
61- if envvar .SourcegraphDotComMode () || ! conf .HasGitHubDotComToken () {
62- return & gitserver.Repo {Name : repo , URL : "https://" + string (repo ) + ".git" }
63- }
70+ case strings .HasPrefix (lowerRepo , "github.com/" ):
71+ hasToken = hasGitHubDotComToken
72+ case strings .HasPrefix (lowerRepo , "gitlab.com/" ):
73+ hasToken = hasGitLabDotComToken
74+ default :
75+ return nil , nil
76+ }
6477
65- case strings .HasPrefix (strings .ToLower (string (repo )), "gitlab.com/" ):
66- if envvar .SourcegraphDotComMode () || ! conf .HasGitLabDotComToken () {
67- return & gitserver.Repo {Name : repo , URL : "https://" + string (repo ) + ".git" }
68- }
78+ r := & gitserver.Repo {Name : repo , URL : "https://" + string (repo ) + ".git" }
79+ if envvar .SourcegraphDotComMode () {
80+ return r , nil
81+ }
82+
83+ ok , err := hasToken (ctx )
84+ if err != nil {
85+ return nil , err
86+ }
87+ if ! ok {
88+ return r , nil
6989 }
7090
7191 // Fall back to performing full RepoLookup, which will hit the code host.
72- return nil
92+ return nil , nil
93+ }
94+
95+ // hasGitHubDotComToken reports whether there are any personal access tokens configured for
96+ // github.com.
97+ func hasGitHubDotComToken (ctx context.Context ) (bool , error ) {
98+ conns , err := db .ExternalServices .ListGitHubConnections (ctx )
99+ if err != nil {
100+ return false , err
101+ }
102+ for _ , c := range conns {
103+ u , err := url .Parse (c .Url )
104+ if err != nil {
105+ continue
106+ }
107+ hostname := strings .ToLower (u .Hostname ())
108+ if (hostname == "github.com" || hostname == "api.github.com" ) && c .Token != "" {
109+ return true , nil
110+ }
111+ }
112+ return false , nil
113+ }
114+
115+ // hasGitLabDotComToken reports whether there are any personal access tokens configured for
116+ // github.com.
117+ func hasGitLabDotComToken (ctx context.Context ) (bool , error ) {
118+ conns , err := db .ExternalServices .ListGitLabConnections (ctx )
119+ if err != nil {
120+ return false , err
121+ }
122+ for _ , c := range conns {
123+ u , err := url .Parse (c .Url )
124+ if err != nil {
125+ continue
126+ }
127+ hostname := strings .ToLower (u .Hostname ())
128+ if hostname == "gitlab.com" && c .Token != "" {
129+ return true , nil
130+ }
131+ }
132+ return false , nil
73133}
74134
75135// ResolveRev will return the absolute commit for a commit-ish spec in a repo.
0 commit comments