@@ -117,10 +117,56 @@ Authorization: Bearer RANDOM-TOKEN
117117# We can't disable timeouts on Bazel, but we can set them to large values.
118118_GO_REPOSITORY_TIMEOUT = 86400
119119
120+ def _escape_go_module_path (module_path ):
121+ """Escapes a Go module path according to the Go proxy protocol."""
122+ result = ""
123+ for c in module_path .elems ():
124+ if "A" <= c and c <= "Z" :
125+ result += "!" + c .lower ()
126+ else :
127+ result += c
128+ return result
129+
130+ def _get_goproxy_url_for_module (env , module_path ):
131+ """Return proxy URL to be used for module_path, or None if no proxy will be used."""
132+ goproxy = env .get ("GOPROXY" , "" )
133+ goprivate = env .get ("GOPRIVATE" , "" )
134+ gonoproxy = env .get ("GONOPROXY" , "" )
135+
136+ if goproxy == "off" :
137+ return None
138+
139+ def matches_pattern (pattern , module_path ):
140+ pat = pattern .strip ()
141+ if not pat :
142+ return False
143+ if pat .endswith ("/..." ):
144+ return module_path .startswith (pat [:- 4 ])
145+ if "*" in pat :
146+ return pat .replace ("*" , "" ) in module_path
147+ return module_path .startswith (pat )
148+
149+ for pat in goprivate .split ("," ) + gonoproxy .split ("," ):
150+ if matches_pattern (pat , module_path ):
151+ return None
152+
153+ if not goproxy :
154+ return "https://proxy.golang.org"
155+
156+ idx = goproxy .find ("," )
157+ if idx != - 1 :
158+ goproxy = goproxy [:idx ]
159+
160+ if goproxy == "direct" :
161+ return None
162+
163+ return goproxy
164+
120165def _go_repository_impl (ctx ):
121166 # TODO(#549): vcs repositories are not cached and still need to be fetched.
122167 # Download the repository or module.
123168 fetch_repo_args = None
169+ sum_args = []
124170 gazelle_path = None
125171
126172 is_module_extension_repo = bool (ctx .attr .internal_only_do_not_use_apparent_name )
@@ -137,6 +183,7 @@ def _go_repository_impl(ctx):
137183 gazelle_path = ctx .path (Label (_gazelle ))
138184 watch (ctx , gazelle_path )
139185
186+ can_use_direct_download = False
140187 reproducible = False
141188 if ctx .attr .local_path :
142189 if hasattr (ctx , "watch_tree" ):
@@ -204,14 +251,15 @@ def _go_repository_impl(ctx):
204251 else :
205252 fail ("if version is specified, sum must also be" )
206253 reproducible = True
254+ can_use_direct_download = True
207255
208256 fetch_path = ctx .attr .replace if ctx .attr .replace else ctx .attr .importpath
257+ sum_args = ["-sum=" + ctx .attr .sum ]
209258 fetch_repo_args = [
210259 "-dest=" + str (ctx .path ("" )),
211260 "-importpath=" + fetch_path ,
212261 "-version=" + ctx .attr .version ,
213- "-sum=" + ctx .attr .sum ,
214- ]
262+ ] + sum_args
215263 else :
216264 fail ("one of urls, commit, tag, or version must be specified" )
217265
@@ -286,6 +334,28 @@ def _go_repository_impl(ctx):
286334 # Override external GO111MODULE, because it is needed by module mode, no-op in repository mode
287335 fetch_repo_env ["GO111MODULE" ] = "on"
288336
337+ if can_use_direct_download :
338+ module = ctx .attr .replace if ctx .attr .replace else ctx .attr .importpath
339+ proxy_url = _get_goproxy_url_for_module (env , module )
340+
341+ if proxy_url :
342+ result = ctx .download_and_extract (
343+ url = "%s/%s/@v/%s.zip" % (
344+ proxy_url ,
345+ _escape_go_module_path (module ),
346+ ctx .attr .version ,
347+ ),
348+ sha256 = ctx .attr .sha256 ,
349+ canonical_id = ctx .attr .canonical_id ,
350+ stripPrefix = module + "@" + ctx .attr .version ,
351+ type = ctx .attr .type ,
352+ auth = use_netrc (read_user_netrc (ctx ), ctx .attr .urls , ctx .attr .auth_patterns ),
353+ allow_fail = True ,
354+ )
355+ if result .success :
356+ # All we need to do now is verify the sum!
357+ fetch_repo_args = ["-no-fetch" ] + fetch_repo_args
358+
289359 result = env_execute (
290360 ctx ,
291361 [fetch_repo ] + fetch_repo_args ,
0 commit comments