Skip to content

Commit

Permalink
go_download_sdk: apply extraction workaround to zips on non-windows OSs
Browse files Browse the repository at this point in the history
The Go distribution contains at least one test file with an invalid
unicode name. Bazel cannot extract the distribution archive on some
operating systems and file systems; Darwin with AFS at least is affected.

For .tar.gz files, we workaround the failure in ctx.download_and_extract
by using the native system tar.

This PR applies a similar workaround for .zip files on non-Windows OSs.
Windows itself is not affected (ctx.download_and_extract works),
so the workaround is not applied there. This is only really needed
when you have a Darwin host and a Windows executor (don't ask).

For bazel-contrib#2771
  • Loading branch information
jayconrod committed May 17, 2023
1 parent 5933b6e commit f07c175
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 7 deletions.
28 changes: 22 additions & 6 deletions go/private/sdk.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -405,14 +405,17 @@ def _register_toolchains(repo):
def _remote_sdk(ctx, urls, strip_prefix, sha256):
if len(urls) == 0:
fail("no urls specified")
host_goos, _ = _detect_host_platform(ctx)

ctx.report_progress("Downloading and extracting Go toolchain")

# BUG(#2771): Use a system tool to extract the archive instead of
# Bazel's implementation. With some configurations (macOS + Docker +
# some particular file system binding), Bazel's implementation rejects
# files with invalid unicode names. Go has at least one test case with a
# file like this, but we haven't been able to reproduce the failure, so
# instead, we use this workaround.
if urls[0].endswith(".tar.gz"):
# BUG(#2771): Use a system tool to extract the archive instead of
# Bazel's implementation. With some configurations (macOS + Docker +
# some particular file system binding), Bazel's implementation rejects
# files with invalid unicode names. Go has at least one test case with a
# file like this, but we haven't been able to reproduce the failure, so
# instead, we use this workaround.
if strip_prefix != "go":
fail("strip_prefix not supported")
ctx.download(
Expand All @@ -424,6 +427,19 @@ def _remote_sdk(ctx, urls, strip_prefix, sha256):
if res.return_code:
fail("error extracting Go SDK:\n" + res.stdout + res.stderr)
ctx.delete("go_sdk.tar.gz")
elif urls[0].endswith(".zip") and host_goos != "windows":
# Bazel on Windows does not have this bug, but we still need this
# workaround to extract a Windows .zip file from a Darwin or Linux host.
if strip_prefix != "go":
fail("strip_prefix not supported")
ctx.download(
url = urls,
sha256 = sha256,
output = "go_sdk.zip",
)
res = ctx.execute(["bash", "-c", "unzip go_sdk.zip && mv go/* . && rmdir go"])
if res.return_code:
fail("error extracting Go SDK:\n" + res.stdout + res.stderr)
else:
ctx.download_and_extract(
url = urls,
Expand Down
26 changes: 25 additions & 1 deletion tests/core/go_download_sdk/go_download_sdk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ func Test(t *testing.T) {
for _, test := range []struct {
desc, rule string
optToWantVersion map[string]string
fetchOnly string
}{
{
desc: "version",
Expand All @@ -70,7 +71,8 @@ go_download_sdk(
`,
optToWantVersion: map[string]string{"": "go1.16"},
}, {
},
{
desc: "custom_archives",
rule: `
load("@io_bazel_rules_go//go:deps.bzl", "go_download_sdk")
Expand Down Expand Up @@ -114,6 +116,21 @@ go_download_sdk(
"--@io_bazel_rules_go//go/toolchain:sdk_version=1.17.1": "go1.17.1",
},
},
{
// Cover workaround for #2771.
desc: "windows_zip",
rule: `
load("@io_bazel_rules_go//go:deps.bzl", "go_download_sdk")
go_download_sdk(
name = "go_sdk",
goarch = "amd64",
goos = "windows",
version = "1.20.4",
)
`,
fetchOnly: "@go_sdk//:BUILD.bazel",
},
} {
t.Run(test.desc, func(t *testing.T) {
origWorkspaceData, err := ioutil.ReadFile("WORKSPACE")
Expand Down Expand Up @@ -143,6 +160,13 @@ go_register_toolchains()
}
}()

if test.fetchOnly != "" {
if err := bazel_testing.RunBazel("fetch", test.fetchOnly); err != nil {
t.Fatal(err)
}
return
}

for opt, wantVersion := range test.optToWantVersion {
t.Run(wantVersion, func(t *testing.T) {
args := []string{
Expand Down

0 comments on commit f07c175

Please sign in to comment.