Repository: bazelbuild/bazelisk
Pull request #397 (2022-11-19 20:24:30)

Support aarch64 in `bazelisk.py`.
Linux reports arm64 as aarch64. Correct for this so that Bazel can be fetched when on arm64/aarch64.

google-cla[bot]: Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this [failed invocation](https://github.com/bazelbuild/bazelisk/pull/397/checks?check_run_id=9594514027) of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

Patch:
diff --git a/.bazelversion b/.bazelversion
index 03f488b..09b254e 100644
--- a/.bazelversion
+++ b/.bazelversion
@@ -1,1 +1,1 @@
-5.3.0
+6.0.0
diff --git a/BUILD b/BUILD
index eb7e9e1..9d98259 100644
--- a/BUILD
+++ b/BUILD
@@ -102,8 +102,8 @@ go_binary(
 genrule(
     name = "bazelisk-darwin-universal",
     srcs = [
-        ":bazelisk-darwin_amd64",
-        ":bazelisk-darwin_arm64",
+        ":bazelisk-darwin-amd64",
+        ":bazelisk-darwin-arm64",
     ],
     outs = ["bazelisk-darwin_universal"],
     cmd = "lipo -create -output \"$@\" $(SRCS)",
@@ -151,61 +151,21 @@ go_binary(
     visibility = ["//visibility:public"],
 )
 
-genrule(
-    name = "bazelisk-darwin-amd64-for-npm",
-    srcs = [":bazelisk-darwin-amd64"],
-    outs = ["bazelisk-darwin_amd64"],
-    cmd = "cp $(location :bazelisk-darwin-amd64) \"$@\"",
-    output_to_bindir = 1,
-)
-
-genrule(
-    name = "bazelisk-darwin-arm64-for-npm",
-    srcs = [":bazelisk-darwin-arm64"],
-    outs = ["bazelisk-darwin_arm64"],
-    cmd = "cp $(location :bazelisk-darwin-arm64) \"$@\"",
-    output_to_bindir = 1,
-)
-
-genrule(
-    name = "bazelisk-linux-amd64-for-npm",
-    srcs = [":bazelisk-linux-amd64"],
-    outs = ["bazelisk-linux_amd64"],
-    cmd = "cp $(location :bazelisk-linux-amd64) \"$@\"",
-    output_to_bindir = 1,
-)
-
-genrule(
-    name = "bazelisk-linux-arm64-for-npm",
-    srcs = [":bazelisk-linux-arm64"],
-    outs = ["bazelisk-linux_arm64"],
-    cmd = "cp $(location :bazelisk-linux-arm64) \"$@\"",
-    output_to_bindir = 1,
-)
-
-genrule(
-    name = "bazelisk-windows-amd64-for-npm",
-    srcs = [":bazelisk-windows-amd64"],
-    outs = ["bazelisk-windows_amd64.exe"],
-    cmd = "cp $(location :bazelisk-windows-amd64) \"$@\"",
-    output_to_bindir = 1,
-)
-
 pkg_npm(
     name = "npm_package",
     package_name = "@bazel/bazelisk",
     srcs = [
         "LICENSE",
         "README.md",
-        "bazelisk.js",
         "bazelisk.d.ts",
+        "bazelisk.js",
         "package.json",
     ],
     deps = [
-        ":bazelisk-darwin-amd64-for-npm",
-        ":bazelisk-darwin-arm64-for-npm",
-        ":bazelisk-linux-amd64-for-npm",
-        ":bazelisk-linux-arm64-for-npm",
-        ":bazelisk-windows-amd64-for-npm",
+        ":bazelisk-darwin-amd64",
+        ":bazelisk-darwin-arm64",
+        ":bazelisk-linux-amd64",
+        ":bazelisk-linux-arm64",
+        ":bazelisk-windows-amd64",
     ],
 )
diff --git a/WORKSPACE b/WORKSPACE
index 089caf6..4304243 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -2,19 +2,19 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 
 http_archive(
     name = "io_bazel_rules_go",
-    sha256 = "69de5c704a05ff37862f7e0f5534d4f479418afc21806c887db544a316f3cb6b",
+    sha256 = "56d8c5a5c91e1af73eca71a6fab2ced959b67c86d12ba37feedb0a2dfea441a6",
     urls = [
-        "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.27.0/rules_go-v0.27.0.tar.gz",
-        "https://github.com/bazelbuild/rules_go/releases/download/v0.27.0/rules_go-v0.27.0.tar.gz",
+        "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.37.0/rules_go-v0.37.0.zip",
+        "https://github.com/bazelbuild/rules_go/releases/download/v0.37.0/rules_go-v0.37.0.zip",
     ],
 )
 
 http_archive(
     name = "bazel_gazelle",
-    sha256 = "62ca106be173579c0a167deb23358fdfe71ffa1e4cfdddf5582af26520f1c66f",
+    sha256 = "448e37e0dbf61d6fa8f00aaa12d191745e14f07c31cabfa731f0c8e8a4f41b97",
     urls = [
-        "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.23.0/bazel-gazelle-v0.23.0.tar.gz",
-        "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.23.0/bazel-gazelle-v0.23.0.tar.gz",
+        "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.28.0/bazel-gazelle-v0.28.0.tar.gz",
+        "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.28.0/bazel-gazelle-v0.28.0.tar.gz",
     ],
 )
 
@@ -24,15 +24,15 @@ load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies", "go_repository")
 go_repository(
     name = "com_github_bazelbuild_rules_go",
     importpath = "github.com/bazelbuild/rules_go",
-    sum = "h1:KViqR7qKXwz+LrNdIauCDU21kneCk+4DnYjpvlJwH50=",
-    version = "v0.27.0",
+    sum = "h1:vbnESGv/t2WgGEbXatwbXAS95dTx93Lv6Uh5QkVF13s=",
+    version = "v0.37.0",
 )
 
 go_repository(
     name = "com_github_hashicorp_go_version",
     importpath = "github.com/hashicorp/go-version",
-    sum = "h1:McDWVJIU/y+u1BRV06dPaLfLCaT7fUTJLp5r04x7iNw=",
-    version = "v1.3.0",
+    sum = "h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=",
+    version = "v1.6.0",
 )
 
 go_repository(
@@ -52,7 +52,7 @@ go_repository(
 
 go_rules_dependencies()
 
-go_register_toolchains(version = "1.16.4")
+go_register_toolchains(version = "1.19.4")
 
 gazelle_dependencies()
 
diff --git a/bazelisk.py b/bazelisk.py
index 0b8e953..44f4256 100755
--- a/bazelisk.py
+++ b/bazelisk.py
@@ -258,6 +258,8 @@ def normalized_machine_arch_name():
     machine = platform.machine().lower()
     if machine == "amd64":
         machine = "x86_64"
+    elif machine == "aarch64":
+        machine = "arm64"
     return machine
 
 
diff --git a/core/BUILD b/core/BUILD
index fee6d3a..2f5ec60 100644
--- a/core/BUILD
+++ b/core/BUILD
@@ -1,4 +1,4 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_library")
+load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
 
 go_library(
     name = "go_default_library",
@@ -16,3 +16,9 @@ go_library(
         "@com_github_mitchellh_go_homedir//:go_default_library",
     ],
 )
+
+go_test(
+    name = "go_default_test",
+    srcs = ["core_test.go"],
+    embed = [":go_default_library"],
+)
diff --git a/core/core.go b/core/core.go
index 91235b5..01f5f68 100644
--- a/core/core.go
+++ b/core/core.go
@@ -5,6 +5,7 @@ package core
 
 import (
 	"bufio"
+	"crypto/sha256"
 	"fmt"
 	"io"
 	"io/ioutil"
@@ -14,6 +15,7 @@ import (
 	"os/signal"
 	"path/filepath"
 	"regexp"
+	"runtime"
 	"sort"
 	"strings"
 	"sync"
@@ -30,6 +32,7 @@ const (
 	skipWrapperEnv = "BAZELISK_SKIP_WRAPPER"
 	wrapperPath    = "./tools/bazel"
 	rcFileName     = ".bazeliskrc"
+	maxDirLength   = 255
 )
 
 var (
@@ -103,7 +106,7 @@ func RunBazeliskWithArgsFunc(argsFunc ArgsFunc, repos *Repositories) (int, error
 		}
 
 		baseDirectory := filepath.Join(bazeliskHome, "downloads", bazelForkOrURL)
-		bazelPath, err = downloadBazel(bazelFork, resolvedBazelVersion, baseDirectory, repos, downloader)
+		bazelPath, err = downloadBazel(resolvedBazelVersion, baseDirectory, repos, downloader)
 		if err != nil {
 			return -1, fmt.Errorf("could not download Bazel: %v", err)
 		}
@@ -401,7 +404,7 @@ func parseBazelForkAndVersion(bazelForkAndVersion string) (string, string, error
 	return bazelFork, bazelVersion, nil
 }
 
-func downloadBazel(fork string, version string, baseDirectory string, repos *Repositories, downloader DownloadFunc) (string, error) {
+func downloadBazel(version string, baseDirectory string, repos *Repositories, downloader DownloadFunc) (string, error) {
 	pathSegment, err := platforms.DetermineBazelFilename(version, false)
 	if err != nil {
 		return "", fmt.Errorf("could not determine path segment to use for Bazel binary: %v", err)
@@ -456,23 +459,39 @@ func linkLocalBazel(baseDirectory string, bazelPath string) (string, error) {
 	return destinationPath, nil
 }
 
-func maybeDelegateToWrapper(bazel string) string {
-	if GetEnvOrConfig(skipWrapperEnv) != "" {
-		return bazel
-	}
-
-	wd, err := os.Getwd()
-	if err != nil {
+func maybeDelegateToWrapperFromDir(bazel string, wd string, ignoreEnv bool) string {
+	if !ignoreEnv && GetEnvOrConfig(skipWrapperEnv) != "" {
 		return bazel
 	}
 
 	root := findWorkspaceRoot(wd)
 	wrapper := filepath.Join(root, wrapperPath)
-	if stat, err := os.Stat(wrapper); err != nil || stat.IsDir() || stat.Mode().Perm()&0111 == 0 {
+	if stat, err := os.Stat(wrapper); err == nil && !stat.Mode().IsDir() && stat.Mode().Perm()&0111 != 0 {
+		return wrapper
+	}
+
+	if runtime.GOOS == "windows" {
+		powershellWrapper := filepath.Join(root, wrapperPath + ".ps1")
+		if stat, err := os.Stat(powershellWrapper); err == nil && !stat.Mode().IsDir() {
+			return powershellWrapper
+		}
+
+		batchWrapper := filepath.Join(root, wrapperPath + ".bat")
+		if stat, err := os.Stat(batchWrapper); err == nil && !stat.Mode().IsDir() {
+			return batchWrapper
+		}
+	}
+
+	return bazel
+}
+
+func maybeDelegateToWrapper(bazel string) string {
+	wd, err := os.Getwd()
+	if err != nil {
 		return bazel
 	}
 
-	return wrapper
+	return maybeDelegateToWrapperFromDir(bazel, wd, false)
 }
 
 func prependDirToPathList(cmd *exec.Cmd, dir string) {
@@ -729,5 +748,12 @@ func migrate(bazelPath string, baseArgs []string, flags []string) {
 
 func dirForURL(url string) string {
 	// Replace all characters that might not be allowed in filenames with "-".
-	return regexp.MustCompile("[[:^alnum:]]").ReplaceAllString(url, "-")
+	dir := regexp.MustCompile("[[:^alnum:]]").ReplaceAllString(url, "-")
+	// Work around length limit on some systems by truncating and then appending
+	// a sha256 hash of the URL.
+	if len(dir) > maxDirLength {
+		suffix := fmt.Sprintf("...%x", sha256.Sum256([]byte(url)))
+		dir = dir[:maxDirLength-len(suffix)] + suffix
+	}
+	return dir
 }
diff --git a/go.mod b/go.mod
index b433331..fb48e45 100644
--- a/go.mod
+++ b/go.mod
@@ -1,9 +1,9 @@
 module github.com/bazelbuild/bazelisk
 
-go 1.15
+go 1.18
 
 require (
-	github.com/bazelbuild/rules_go v0.34.0
+	github.com/bazelbuild/rules_go v0.38.1
 	github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d
 	github.com/hashicorp/go-version v1.6.0
 	github.com/mitchellh/go-homedir v1.1.0
diff --git a/go.sum b/go.sum
index e5ef5fd..bf171a5 100644
--- a/go.sum
+++ b/go.sum
@@ -1,5 +1,5 @@
-github.com/bazelbuild/rules_go v0.34.0 h1:cmObMtgIOaEU944SqXtJ9DnlS8IPGGa7pdRnsrpQzXM=
-github.com/bazelbuild/rules_go v0.34.0/go.mod h1:MC23Dc/wkXEyk3Wpq6lCqz0ZAYOZDw2DR5y3N1q2i7M=
+github.com/bazelbuild/rules_go v0.38.1 h1:YGNsLhWe18Ielebav7cClP3GMwBxBE+xEArLHtmXDx8=
+github.com/bazelbuild/rules_go v0.38.1/go.mod h1:TMHmtfpvyfsxaqfL9WnahCsXMWDMICTw7XeK9yVb+YU=
 github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
 github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
 github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
diff --git a/repositories/github.go b/repositories/github.go
index f03fd6a..0d02067 100644
--- a/repositories/github.go
+++ b/repositories/github.go
@@ -52,7 +52,11 @@ func (gh *GitHubRepo) getFilteredVersions(bazeliskHome, bazelFork string, wantPr
 	}
 
 	url := fmt.Sprintf("https://api.github.com/repos/%s/bazel/releases", bazelFork)
-	releasesJSON, err := httputil.MaybeDownload(bazeliskHome, url, bazelFork+"-releases.json", "list of Bazel releases from github.com/"+bazelFork, fmt.Sprintf("token %s", gh.token), merger)
+	auth := ""
+	if gh.token != "" {
+		auth = fmt.Sprintf("token %s", gh.token)
+	}
+	releasesJSON, err := httputil.MaybeDownload(bazeliskHome, url, bazelFork+"-releases.json", "list of Bazel releases from github.com/"+bazelFork, auth, merger)
 	if err != nil {
 		return []string{}, fmt.Errorf("unable to determine '%s' releases: %v", bazelFork, err)
 	}


Test patch:
diff --git a/core/core_test.go b/core/core_test.go
new file mode 100644
index 0000000..9f1dea8
--- /dev/null
+++ b/core/core_test.go
@@ -0,0 +1,169 @@
+package core
+
+import (
+	"io/ioutil"
+	"log"
+	"os"
+	"path/filepath"
+	"runtime"
+	"testing"
+)
+
+func TestMaybeDelegateToNoWrapper(t *testing.T) {
+	tmpDir, err := ioutil.TempDir("", "TestMaybeDelegateToNoWrapper")
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer os.RemoveAll(tmpDir)
+
+	os.MkdirAll(tmpDir, os.ModeDir | 0700)
+	ioutil.WriteFile(filepath.Join(tmpDir, "WORKSPACE"), []byte(""), 0600)
+	ioutil.WriteFile(filepath.Join(tmpDir, "BUILD"), []byte(""), 0600)
+
+	entrypoint := maybeDelegateToWrapperFromDir("bazel_real", tmpDir, true)
+	expected := "bazel_real"
+
+	if entrypoint != expected {
+		t.Fatalf("Expected to delegate bazel to %q, but got %q", expected, entrypoint)
+	}
+}
+
+func TestMaybeDelegateToNoNonExecutableWrapper(t *testing.T) {
+	// It's not guaranteed that `tools/bazel` is executable on the
+	// Windows host running this test. Thus the test is skipped on
+	// this platform to guarantee consistent results.
+	if runtime.GOOS == "windows" {
+		return
+	}
+	
+	tmpDir, err := ioutil.TempDir("", "TestMaybeDelegateToNoNonExecutableWrapper")
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer os.RemoveAll(tmpDir)
+
+	os.MkdirAll(tmpDir, os.ModeDir | 0700)
+	ioutil.WriteFile(filepath.Join(tmpDir, "WORKSPACE"), []byte(""), 0600)
+	ioutil.WriteFile(filepath.Join(tmpDir, "BUILD"), []byte(""), 0600)
+
+	os.MkdirAll(filepath.Join(tmpDir, "tools"), os.ModeDir | 0700)
+	ioutil.WriteFile(filepath.Join(tmpDir, "tools", "bazel"), []byte(""), 0600)
+
+	entrypoint := maybeDelegateToWrapperFromDir("bazel_real", tmpDir, true)
+	expected := "bazel_real"
+
+	if entrypoint != expected {
+		t.Fatalf("Expected to delegate bazel to %q, but got %q", expected, entrypoint)
+	}
+}
+
+func TestMaybeDelegateToStandardWrapper(t *testing.T) {
+	// It's not guaranteed that `tools/bazel` is executable on the
+	// Windows host running this test. Thus the test is skipped on
+	// this platform to guarantee consistent results.
+	if runtime.GOOS == "windows" {
+		return
+	}
+
+	var tmpDir, err = ioutil.TempDir("", "TestMaybeDelegateToStandardWrapper")
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer os.RemoveAll(tmpDir)
+
+	os.MkdirAll(tmpDir, os.ModeDir | 0700)
+	ioutil.WriteFile(filepath.Join(tmpDir, "WORKSPACE"), []byte(""), 0600)
+	ioutil.WriteFile(filepath.Join(tmpDir, "BUILD"), []byte(""), 0600)
+
+	os.MkdirAll(filepath.Join(tmpDir, "tools"), os.ModeDir | 0700)
+	ioutil.WriteFile(filepath.Join(tmpDir, "tools", "bazel"), []byte(""), 0700)
+
+	entrypoint := maybeDelegateToWrapperFromDir("bazel_real", tmpDir, true)
+	expected := filepath.Join(tmpDir, "tools", "bazel")
+
+	if entrypoint != expected {
+		t.Fatalf("Expected to delegate bazel to %q, but got %q", expected, entrypoint)
+	}
+}
+
+func TestMaybeDelegateToPowershellWrapper(t *testing.T) {
+	tmpDir, err := ioutil.TempDir("", "TestMaybeDelegateToPowershellWrapper")
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer os.RemoveAll(tmpDir)
+
+	os.MkdirAll(tmpDir, os.ModeDir | 0700)
+	ioutil.WriteFile(filepath.Join(tmpDir, "WORKSPACE"), []byte(""), 0600)
+	ioutil.WriteFile(filepath.Join(tmpDir, "BUILD"), []byte(""), 0600)
+
+	os.MkdirAll(filepath.Join(tmpDir, "tools"), os.ModeDir | 0700)
+	ioutil.WriteFile(filepath.Join(tmpDir, "tools", "bazel.ps1"), []byte(""), 0700)
+
+	entrypoint := maybeDelegateToWrapperFromDir("bazel_real", tmpDir, true)
+	expected := filepath.Join(tmpDir, "tools", "bazel.ps1")
+
+	// Only windows platforms use powershell wrappers
+	if runtime.GOOS != "windows" {
+		expected = "bazel_real"
+	}
+
+	if entrypoint != expected {
+		t.Fatalf("Expected to delegate bazel to %q, but got %q", expected, entrypoint)
+	}
+}
+
+func TestMaybeDelegateToBatchWrapper(t *testing.T) {
+	tmpDir, err := ioutil.TempDir("", "TestMaybeDelegateToBatchWrapper")
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer os.RemoveAll(tmpDir)
+
+	os.MkdirAll(tmpDir, os.ModeDir | 0700)
+	ioutil.WriteFile(filepath.Join(tmpDir, "WORKSPACE"), []byte(""), 0600)
+	ioutil.WriteFile(filepath.Join(tmpDir, "BUILD"), []byte(""), 0600)
+
+	os.MkdirAll(filepath.Join(tmpDir, "tools"), os.ModeDir | 0700)
+	ioutil.WriteFile(filepath.Join(tmpDir, "tools", "bazel.bat"), []byte(""), 0700)
+
+	entrypoint := maybeDelegateToWrapperFromDir("bazel_real", tmpDir, true)
+	expected := filepath.Join(tmpDir, "tools", "bazel.bat")
+
+	// Only windows platforms use batch wrappers
+	if runtime.GOOS != "windows" {
+		expected = "bazel_real"
+	}
+
+	if entrypoint != expected {
+		t.Fatalf("Expected to delegate bazel to %q, but got %q", expected, entrypoint)
+	}
+}
+
+func TestMaybeDelegateToPowershellOverBatchWrapper(t *testing.T) {
+	tmpDir, err := ioutil.TempDir("", "TestMaybeDelegateToPowershellOverBatchWrapper")
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer os.RemoveAll(tmpDir)
+
+	os.MkdirAll(tmpDir, os.ModeDir | 0700)
+	ioutil.WriteFile(filepath.Join(tmpDir, "WORKSPACE"), []byte(""), 0600)
+	ioutil.WriteFile(filepath.Join(tmpDir, "BUILD"), []byte(""), 0600)
+
+	os.MkdirAll(filepath.Join(tmpDir, "tools"), os.ModeDir | 0700)
+	ioutil.WriteFile(filepath.Join(tmpDir, "tools", "bazel.ps1"), []byte(""), 0700)
+	ioutil.WriteFile(filepath.Join(tmpDir, "tools", "bazel.bat"), []byte(""), 0700)
+
+	entrypoint := maybeDelegateToWrapperFromDir("bazel_real", tmpDir, true)
+	expected := filepath.Join(tmpDir, "tools", "bazel.ps1")
+
+	// Only windows platforms use powershell or batch wrappers
+	if runtime.GOOS != "windows" {
+		expected = "bazel_real"
+	}
+
+	if entrypoint != expected {
+		t.Fatalf("Expected to delegate bazel to %q, but got %q", expected, entrypoint)
+	}
+}