Skip to content

Commit 78f1456

Browse files
committed
Use bazel's downloader for Go modules when possible
1 parent 3e438c8 commit 78f1456

File tree

3 files changed

+85
-2
lines changed

3 files changed

+85
-2
lines changed

cmd/fetch_repo/main.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ package main
2727
import (
2828
"flag"
2929
"log"
30+
"os"
3031

32+
"golang.org/x/mod/sumdb/dirhash"
3133
"golang.org/x/tools/go/vcs"
3234
)
3335

@@ -70,7 +72,19 @@ func main() {
7072
}
7173

7274
if *no_fetch {
73-
// Nothing to do
75+
if *sum != "" {
76+
repoSum, err := dirhash.HashDir(*dest, *importpath+"@"+*version, dirhash.Hash1)
77+
if err != nil {
78+
log.Fatalf("failed computing sum: %v", err)
79+
}
80+
81+
if repoSum != *sum {
82+
if goModCache := os.Getenv("GOMODCACHE"); goModCache != "" {
83+
log.Fatalf("resulting module with sum %s; expected sum %s, Please try clearing your module cache directory %q", repoSum, *sum, goModCache)
84+
}
85+
log.Fatalf("resulting module with sum %s; expected sum %s", repoSum, *sum)
86+
}
87+
}
7488
} else if *path != "" {
7589
if *importpath != "" {
7690
log.Fatal("-importpath must not be set")

internal/go_repository.bzl

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
120165
def _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,

internal/go_repository_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ go_repository(
180180
}
181181

182182
func TestModcacheRW(t *testing.T) {
183-
if err := bazel_testing.RunBazel("query", "@errors_go_mod//:go_default_library"); err != nil {
183+
if err := bazel_testing.RunBazel("query", "--repo_env=GOPROXY=direct", "@errors_go_mod//:go_default_library"); err != nil {
184184
t.Fatal(err)
185185
}
186186
out, err := bazel_testing.BazelOutput("info", "output_base")

0 commit comments

Comments
 (0)