Skip to content

Commit

Permalink
fix(cli): fix case where linkLocalBazel fails when os.UserCacheDir re…
Browse files Browse the repository at this point in the history
…turns path starting with ~ (#1182)

Also run `help flags-as-proto` command in a UserCacheDir() location
instead of the tmp dir and fix order of error handling for the result of
that call. UserCacheDir() is more robust since tmpdir is not guaranteed
to exist or to be writable (as per [golang
docs](https://pkg.go.dev/os#TempDir)). We already depend on
UserCacheDir() in the CLI code.

GitOrigin-RevId: df084e1effce5ba4a813f56b33260e9749c5526d
  • Loading branch information
gregmagolan committed Jan 16, 2023
1 parent bb0946f commit 41988f9
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 11 deletions.
34 changes: 26 additions & 8 deletions pkg/bazel/bazel.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"fmt"
"io"
"os"
"path"
"path/filepath"
"strings"

Expand Down Expand Up @@ -162,6 +163,23 @@ func (b *bazel) Flags() (map[string]*flags.FlagInfo, error) {
if allFlags != nil {
return allFlags, nil
}

// create a directory in the user cache dir with an empty WORKSPACE file to run
// `bazel help flags-as-proto` in so it doesn't affect the bazel server in the user's WORKSPACE
userCacheDir, err := UserCacheDir()
if err != nil {
return nil, fmt.Errorf("failed to get user cache dir: %w", err)
}
tmpdir := path.Join(userCacheDir, ".aspect/cli-flags-as-proto")
err = os.MkdirAll(tmpdir, os.ModePerm)
if err != nil {
return nil, fmt.Errorf("failed write create directory %s: %w", tmpdir, err)
}
err = os.WriteFile(path.Join(tmpdir, "WORKSPACE"), []byte{}, 0644)
if err != nil {
return nil, fmt.Errorf("failed write WORKSPACE file in %s: %w", tmpdir, err)
}

var stdout bytes.Buffer
var stderr bytes.Buffer
streams := ioutils.Streams{
Expand All @@ -174,23 +192,23 @@ func (b *bazel) Flags() (map[string]*flags.FlagInfo, error) {
bazelExitCode := make(chan int, 1)
defer close(bazelErrs)
defer close(bazelExitCode)
go func() {

go func(wd string) {
// Running in batch mode will prevent bazel from spawning a daemon. Spawning a bazel daemon takes time which is something we don't want here.
// Also, instructing bazel to ignore all rc files will protect it from failing if any of the rc files is broken.
tmpdir := os.TempDir()
exitCode, err := b.RunCommand(streams, &tmpdir, "--nobatch", "--ignore_all_rc_files", "help", "flags-as-proto")
exitCode, err := b.RunCommand(streams, &wd, "--nobatch", "--ignore_all_rc_files", "help", "flags-as-proto")
bazelErrs <- err
bazelExitCode <- exitCode
}()

if exitCode := <-bazelExitCode; exitCode != 0 {
return nil, fmt.Errorf("failed to get bazel flags: %w", fmt.Errorf("bazel has quit with code %d\nstderr:\n%s", exitCode, stderr.String()))
}
}(tmpdir)

if err := <-bazelErrs; err != nil {
return nil, fmt.Errorf("failed to get bazel flags: %w", err)
}

if exitCode := <-bazelExitCode; exitCode != 0 {
return nil, fmt.Errorf("failed to get bazel flags running in %s: %w", tmpdir, fmt.Errorf("bazel has quit with code %d\nstderr:\n%s", exitCode, stderr.String()))
}

helpProtoBytes, err := io.ReadAll(stdoutDecoder)
if err != nil {
return nil, fmt.Errorf("failed to get bazel flags: %w", err)
Expand Down
22 changes: 19 additions & 3 deletions pkg/bazel/bazelisk.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,31 @@ func NewBazelisk(workspaceRoot string) *Bazelisk {
return &Bazelisk{workspaceRoot: workspaceRoot}
}

func UserCacheDir() (string, error) {
userCacheDir, err := os.UserCacheDir()
if err != nil {
return "", fmt.Errorf("could not get the user's cache directory: %v", err)
}

// We hit a case in a bazel-in-bazel test where os.UserCacheDir() return a path starting with '~'.
// Run it through homedir.Expand to turn it into an absolute path incase that happens.
userCacheDir, err = homedir.Expand(userCacheDir)
if err != nil {
return "", fmt.Errorf("could not expand home directory in path: %v", err)
}

return userCacheDir, err
}

// Run runs the main Bazelisk logic for the given arguments and Bazel repositories.
func (bazelisk *Bazelisk) Run(args []string, repos *core.Repositories, streams ioutils.Streams, env []string, wd *string) (int, error) {
httputil.UserAgent = bazelisk.getUserAgent()

bazeliskHome := bazelisk.GetEnvOrConfig("BAZELISK_HOME")
if len(bazeliskHome) == 0 {
userCacheDir, err := os.UserCacheDir()
userCacheDir, err := UserCacheDir()
if err != nil {
return -1, fmt.Errorf("could not get the user's cache directory: %v", err)
return -1, err
}

bazeliskHome = filepath.Join(userCacheDir, "bazelisk")
Expand Down Expand Up @@ -128,7 +144,7 @@ func (bazelisk *Bazelisk) Run(args []string, repos *core.Repositories, streams i
baseDirectory := filepath.Join(bazeliskHome, "local")
bazelPath, err = linkLocalBazel(baseDirectory, bazelPath)
if err != nil {
return -1, fmt.Errorf("cound not link local Bazel: %v", err)
return -1, fmt.Errorf("could not link local Bazel: %v", err)
}
}

Expand Down

0 comments on commit 41988f9

Please sign in to comment.