Skip to content

Commit 3180821

Browse files
authored
Prevent tools/bazel from breaking flags-as-proto parsing (#9350)
1 parent 2658f19 commit 3180821

File tree

3 files changed

+44
-2
lines changed

3 files changed

+44
-2
lines changed

cli/bazelisk/bazelisk.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ var (
2121
setVersionErr error
2222
)
2323

24+
const (
25+
// bazelisk environment variable name that skips tools/bazel if set to a
26+
// non-empty string.
27+
skipWrapperEnvVar = "BAZELISK_SKIP_WRAPPER"
28+
)
29+
2430
type RunOpts struct {
2531
// Stdout is the Writer where bazelisk should write its stdout.
2632
// Defaults to os.Stdout if nil.
@@ -29,9 +35,26 @@ type RunOpts struct {
2935
// Stderr is the Writer where bazelisk should write its stderr.
3036
// Defaults to os.Stderr if nil.
3137
Stderr io.Writer
38+
39+
// SkipWrapper skips the tools/bazel wrapper if it exists.
40+
SkipWrapper bool
3241
}
3342

3443
func Run(args []string, opts *RunOpts) (exitCode int, err error) {
44+
if opts.SkipWrapper {
45+
prev, ok := os.LookupEnv(skipWrapperEnvVar)
46+
if err := os.Setenv(skipWrapperEnvVar, "true"); err != nil {
47+
return -1, fmt.Errorf("failed to set %s: %s", skipWrapperEnvVar, err)
48+
}
49+
// Reset BAZELISK_SKIP_WRAPPER to its previous state after running
50+
// bazelisk.
51+
if ok {
52+
defer os.Setenv(skipWrapperEnvVar, prev)
53+
} else {
54+
defer os.Unsetenv(skipWrapperEnvVar)
55+
}
56+
}
57+
3558
// If we were already invoked via bazelisk, then set the bazel version to
3659
// the next version appearing in the .bazelversion file so that bazelisk
3760
// doesn't just invoke us again (resulting in an infinite loop).
@@ -80,7 +103,7 @@ func Run(args []string, opts *RunOpts) (exitCode int, err error) {
80103
// This will return true when referencing a CLI release in .bazelversion such as
81104
// "buildbuddy-io/0.0.13" and then running `bazelisk`.
82105
func IsInvokedByBazelisk() bool {
83-
return filepath.Base(os.Args[0]) == "bazelisk" || os.Getenv("BAZELISK_SKIP_WRAPPER") == "true"
106+
return filepath.Base(os.Args[0]) == "bazelisk" || os.Getenv(skipWrapperEnvVar) == "true"
84107
}
85108

86109
// makePipeWriter adapts a writer to an *os.File by using an os.Pipe().

cli/parser/parser.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,11 @@ func runBazelHelpWithCache() (string, error) {
503503
buf := &bytes.Buffer{}
504504
errBuf := &bytes.Buffer{}
505505
log.Debugf("\x1b[90mGathering metadata for bazel %s...\x1b[m", topic)
506-
opts := &bazelisk.RunOpts{Stdout: io.MultiWriter(tmp, buf), Stderr: errBuf}
506+
opts := &bazelisk.RunOpts{
507+
Stdout: io.MultiWriter(tmp, buf),
508+
Stderr: errBuf,
509+
SkipWrapper: true,
510+
}
507511
exitCode, err := bazelisk.Run([]string{
508512
"--ignore_all_rc_files",
509513
// Run in a temp output base to avoid messing with any running bazel

cli/test/integration/cli/cli_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,21 @@ startup --host_jvm_args=-DBAZEL_TRACK_SOURCE_DIRECTORIES=1
384384
require.NotContains(t, string(b), "Running Bazel server needs to be killed")
385385
}
386386

387+
func TestHelpWithBazelWrapper(t *testing.T) {
388+
ws := testcli.NewWorkspace(t)
389+
testfs.WriteAllFileContents(t, ws, map[string]string{
390+
"BUILD": "",
391+
"tools/bazel": `#!/usr/bin/env bash
392+
echo "A message from ./tools/bazel that tries to break bb's parsing logic!"
393+
"$BAZEL_REAL" "$@"
394+
`,
395+
})
396+
testfs.MakeExecutable(t, ws, "tools/bazel")
397+
cmd := testcli.BazelCommand(t, ws, "build", "//...")
398+
b, err := testcli.CombinedOutput(cmd)
399+
require.NoErrorf(t, err, "output: %s", string(b))
400+
}
401+
387402
func retryUntilSuccess(t *testing.T, f func() error) {
388403
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
389404
defer cancel()

0 commit comments

Comments
 (0)