@@ -117,6 +117,51 @@ 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.
@@ -137,6 +182,7 @@ def _go_repository_impl(ctx):
137182 gazelle_path = ctx .path (Label (_gazelle ))
138183 watch (ctx , gazelle_path )
139184
185+ can_use_direct_download = False
140186 reproducible = False
141187 if ctx .attr .local_path :
142188 if hasattr (ctx , "watch_tree" ):
@@ -204,6 +250,7 @@ def _go_repository_impl(ctx):
204250 else :
205251 fail ("if version is specified, sum must also be" )
206252 reproducible = True
253+ can_use_direct_download = True
207254
208255 fetch_path = ctx .attr .replace if ctx .attr .replace else ctx .attr .importpath
209256 fetch_repo_args = [
@@ -286,6 +333,28 @@ def _go_repository_impl(ctx):
286333 # Override external GO111MODULE, because it is needed by module mode, no-op in repository mode
287334 fetch_repo_env ["GO111MODULE" ] = "on"
288335
336+ if can_use_direct_download :
337+ module = ctx .attr .replace if ctx .attr .replace else ctx .attr .importpath
338+ proxy_url = _get_goproxy_url_for_module (env , module )
339+
340+ if proxy_url :
341+ result = ctx .download_and_extract (
342+ url = "%s/%s/@v/%s.zip" % (
343+ proxy_url ,
344+ _escape_go_module_path (module ),
345+ ctx .attr .version ,
346+ ),
347+ sha256 = ctx .attr .sha256 ,
348+ canonical_id = ctx .attr .canonical_id ,
349+ stripPrefix = module + "@" + ctx .attr .version ,
350+ type = ctx .attr .type ,
351+ auth = use_netrc (read_user_netrc (ctx ), ctx .attr .urls , ctx .attr .auth_patterns ),
352+ allow_fail = True ,
353+ )
354+ if result .success :
355+ # All we need to do now is verify the sum!
356+ fetch_repo_args = ["-no-fetch" ] + fetch_repo_args
357+
289358 result = env_execute (
290359 ctx ,
291360 [fetch_repo ] + fetch_repo_args ,
0 commit comments