diff --git a/ENVIRONMENT_VARIABLES.md b/ENVIRONMENT_VARIABLES.md index 6f53f8d2..6bc1efa0 100644 --- a/ENVIRONMENT_VARIABLES.md +++ b/ENVIRONMENT_VARIABLES.md @@ -19,4 +19,5 @@ name | default | description `GOENV_AUTO_INSTALL_FLAGS` | | (Note: only works if `GOENV_AUTO_INSTALL` is set to 1) Appends flags to the auto install command (see `goenv install --help` for all available flags) `GOENV_RC_FILE` | `$HOME/.goenvrc` | If `GOENV_RC_FILE` is set, it will be modified accordingly. `GOENV_PATH_ORDER` | | If `GOENV_PATH_ORDER` is set to `front`, `$GOENV_ROOT/shims` will be prepended to the existing `PATH`.Set `GOENV_PATH_ORDER` to a configuration file named by `GOENV_RC_FILE`(e.g. `~/.goenvrc`), for example `GOENV_PATH_ORDER=front` in `~/.goenvrc`. +`GOENV_DISABLE_PATH_WARNING` | `0` | Disables the warning about system Go taking precedence over goenv when shims are at the end of PATH. Set to `1` to disable the warning. `GOENV_AUTOMATICALLY_DETECT_VERSION` | `0` | If set to `1`, goenv will automatically update `GOROOT` and `GOPATH` when you change directories. This enables automatic version switching based on local `.go-version` files without needing to reload your shell configuration. **Note:** This feature adds a hook that runs on every directory change, which may have a slight performance impact. diff --git a/HOW_IT_WORKS.md b/HOW_IT_WORKS.md index cd3895b9..bfc95182 100644 --- a/HOW_IT_WORKS.md +++ b/HOW_IT_WORKS.md @@ -22,21 +22,28 @@ then `/bin`. ## Understanding Shims -goenv works by inserting a directory of _shims_ at the end of your -`PATH`, so if you have `go` in `/usr/bin` it will be found first: +By default, goenv works by inserting a directory of _shims_ at the end of your +`PATH`. This means if you have `go` in `/usr/bin`, it will be found first: /usr/local/bin:/usr/bin:/bin:~/.goenv/shims +**Important:** If you have a system Go installation, you need to configure goenv +to put shims at the front of your PATH. Add `export GOENV_PATH_ORDER=front` to +your `~/.goenvrc` file (or your shell profile). This ensures goenv's shims take +precedence: + + ~/.goenv/shims:/usr/local/bin:/usr/bin:/bin + Through a process called _rehashing_, goenv maintains shims in that directory to match every `go` command across every installed version of Go. Shims are lightweight executables that simply pass your command along -to goenv. So with goenv installed, when you run `go` your +to goenv. So with goenv properly configured, when you run `go` your operating system will do the following: * Search your `PATH` for an executable file named `go` -* Find the goenv shim named `go` at the beginning of your `PATH` +* Find the goenv shim named `go` at the beginning of your `PATH` (if `GOENV_PATH_ORDER=front`) * Run the shim named `go`, which in turn passes the command along to goenv diff --git a/libexec/goenv-init b/libexec/goenv-init index 872356d5..49ebe90f 100755 --- a/libexec/goenv-init +++ b/libexec/goenv-init @@ -86,23 +86,42 @@ mkdir -p "${GOENV_ROOT}/"{shims,versions} case "$shell" in fish) - cat </dev/null) + if test -n "$system_go_path"; and not string match -q "$GOENV_ROOT*" $system_go_path + echo "goenv: WARNING: System 'go' found at $system_go_path" >&2 + echo "goenv: Since your shims are at the end of PATH, system 'go' will be used instead of goenv-managed versions." >&2 + echo "goenv: To fix this, add the following to your $GOENV_RC_FILE:" >&2 + echo "goenv: set -gx GOENV_PATH_ORDER front" >&2 + echo "goenv: Or run: echo 'set -gx GOENV_PATH_ORDER front' >> $GOENV_RC_FILE" >&2 + echo "" >&2 + end +end +EOL + fi ;; *) cat <&2 + echo "goenv: Since your shims are at the end of PATH, system 'go' will be used instead of goenv-managed versions." >&2 + echo "goenv: To fix this, add the following to your ${GOENV_RC_FILE}:" >&2 + echo "goenv: export GOENV_PATH_ORDER=front" >&2 + echo "goenv: Or run: echo 'export GOENV_PATH_ORDER=front' >> ${GOENV_RC_FILE}" >&2 + echo "" >&2 + ;; + esac + fi +fi +EOL + fi ;; esac diff --git a/test/goenv-init.bats b/test/goenv-init.bats index f89c3030..8faf30ec 100644 --- a/test/goenv-init.bats +++ b/test/goenv-init.bats @@ -377,3 +377,52 @@ OUT assert [ -n "$(echo "$output" | grep "__goenv_auto_detect_version")" ] assert [ -n "$(echo "$output" | grep "on-variable PWD")" ] } + +@test "includes PATH collision warning when system go exists and GOENV_PATH_ORDER is not front for bash" { + # Create a fake go binary in PATH + create_executable "${GOENV_TEST_DIR}/bin" "go" + + unset GOENV_DISABLE_PATH_WARNING + run goenv-init - bash + + assert_success + assert_line 'if [ "${GOENV_PATH_ORDER:-}" != "front" ]; then' + assert [ -n "$(echo "$output" | grep 'WARNING: System.*go.*found')" ] +} + +@test "does not include PATH collision warning when GOENV_DISABLE_PATH_WARNING is set to 1" { + create_executable "${GOENV_TEST_DIR}/bin" "go" + + GOENV_DISABLE_PATH_WARNING=1 run goenv-init - bash + + assert_success + refute_line ' system_go_path="$(command -v go 2>/dev/null || true)"' +} + +@test "warning executes and shows message when system go exists and GOENV_PATH_ORDER not set" { + # Create a fake go binary + create_executable "${GOENV_TEST_DIR}/bin" "go" + + # Don't disable the warning for this test + unset GOENV_DISABLE_PATH_WARNING + unset GOENV_PATH_ORDER + + # Eval the init output and capture stderr + run bash -c 'eval "$(GOENV_DISABLE_PATH_WARNING=0 goenv-init - bash 2>&1)" 2>&1' + + assert_success + assert [ -n "$(echo "$output" | grep 'WARNING: System.*go.*found')" ] + assert [ -n "$(echo "$output" | grep 'GOENV_PATH_ORDER=front')" ] +} + +@test "warning does not execute when GOENV_PATH_ORDER is set to front" { + create_executable "${GOENV_TEST_DIR}/bin" "go" + + unset GOENV_DISABLE_PATH_WARNING + export GOENV_PATH_ORDER=front + + run bash -c 'eval "$(GOENV_DISABLE_PATH_WARNING=0 goenv-init - bash 2>&1)" 2>&1' + + assert_success + assert [ -z "$(echo "$output" | grep 'WARNING')" ] +} diff --git a/test/test_helper.bash b/test/test_helper.bash index e723d1c2..9ed1594a 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -3,6 +3,9 @@ load ./test_assert_helpers unset GOENV_VERSION unset GOENV_DIR +# Disable PATH warning in tests to avoid changing expected output +export GOENV_DISABLE_PATH_WARNING=1 + # guard against executing this block twice due to bats internals if [ -z "$GOENV_TEST_DIR" ]; then GOENV_TEST_DIR="${BATS_TMPDIR}/goenv"