From 1c85c8ca4ca9650981f0c2dcc7c9c252895c177c Mon Sep 17 00:00:00 2001 From: Anton Antonov Date: Sun, 10 Mar 2019 02:19:24 +0200 Subject: [PATCH 1/3] Remove duplicate test helper function --- test/goenv-version-name.bats | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/goenv-version-name.bats b/test/goenv-version-name.bats index d814f296..2e0c2dd9 100644 --- a/test/goenv-version-name.bats +++ b/test/goenv-version-name.bats @@ -2,10 +2,6 @@ load test_helper -create_version() { - mkdir -p "${GOENV_ROOT}/versions/$1" -} - setup() { mkdir -p "$GOENV_TEST_DIR" cd "$GOENV_TEST_DIR" From 6e8c81f36a5d064cb9d8ef26f15e4bc935585b71 Mon Sep 17 00:00:00 2001 From: Anton Antonov Date: Sun, 10 Mar 2019 02:20:11 +0200 Subject: [PATCH 2/3] [GH-31] Prepare 2.0.0beta6 --- libexec/goenv---version | 2 +- test/goenv--version.bats | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libexec/goenv---version b/libexec/goenv---version index 36e7b865..03ab5ea6 100755 --- a/libexec/goenv---version +++ b/libexec/goenv---version @@ -6,6 +6,6 @@ set -e [ -n "$GOENV_DEBUG" ] && set -x -version="2.0.0beta5" +version="2.0.0beta6" echo "goenv ${version}" diff --git a/test/goenv--version.bats b/test/goenv--version.bats index 91e37bcc..40f1b1fa 100644 --- a/test/goenv--version.bats +++ b/test/goenv--version.bats @@ -2,7 +2,7 @@ load test_helper -expected_version="goenv 2.0.0beta5" +expected_version="goenv 2.0.0beta6" @test "default version is 'version' variable" { assert [ ! -e "$GOENV_ROOT" ] From f9a06ede89caa566f0d46558044c58c356fa8c6d Mon Sep 17 00:00:00 2001 From: Anton Antonov Date: Sun, 10 Mar 2019 01:50:09 +0200 Subject: [PATCH 3/3] [GH-30][GH-50] Add automatic management of env `GO{PATH,ROOT}` Example usage with default settings for `goenv`: ``` > goenv install 1.12.0 ... > echo $GOROOT /home/syndbg/.goenv/versions/1.12.0 > echo $GOPATH /home/syndbg/go/1.12.0 ``` * Env vars are not managed when version is `system`. This prevents `goenv` being configured, but not used, to mess up with your system Golang setup. * `GOENV_DISABLE_GOROOT` disables management of `GOROOT`. Since this is new behavior that's a very drastic change, optinally disabling it is a must. * `GOENV_DISABLE_GOPATH` disables management of `GOPATH`. Separate configuration of both for whichever reason the end-user may have. * `GOENV_GOPATH_PREFIX` is a configurable prefix used for the managed `GOPATH`. The default is `$HOME/go`. Obviously this won't work for everyone, so it's configurable. * Support for fish, bash, zsh, etc is added. --- CHANGELOG.md | 29 ++++ INSTALL.md | 38 ++++- libexec/goenv-exec | 36 ++++- libexec/goenv-init | 5 + libexec/goenv-sh-rehash | 60 ++++++-- test/goenv-exec.bats | 289 ++++++++++++++++++++++++++++++++++++-- test/goenv-init.bats | 1 - test/goenv-rehash.bats | 6 +- test/goenv-sh-rehash.bats | 236 ++++++++++++++++++++++++++----- test/test_helper.bash | 1 + 10 files changed, 633 insertions(+), 68 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ce3fbbe..b91be8ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,35 @@ Introducing breaking changes under a feature flag can be ok in some cases where ## Unreleased (master) +## 2.0.0beta6 + +### Added + +* Add management of env variable `GOROOT` that can be disabled with env var `GOENV_DISABLE_GOROOT=1`, +when calling `goenv-sh-rehash` (`goenv rehash` when `eval $(goenv init -)` was previously executed). +It does not attempt to manage when version is `system`. +; Ref: https://github.com/syndbg/goenv/pull/70 +* Add management of env variable `GOPATH` that can be disabled with env var `GOENV_DISABLE_GOPATH=1`, +when calling `goenv-sh-rehash` (`goenv rehash` when `eval $(goenv init -)` was previously executed). +It does not attempt to manage when version is `system`. +; Ref: https://github.com/syndbg/goenv/pull/70 +* Add configurable managed `GOPATH` prefix for `goenv-sh-rehash` +(`goenv rehash` when `eval $(goenv init -)` was previously executed). +Configured via `GOENV_GOPATH_PREFIX=`. +E.g `GOENV_GOPATH_PREFIX=/tmp`. +; Ref: https://github.com/syndbg/goenv/pull/70 +* Add `--only-manage-paths` option to `goenv-sh-rehash` (`goenv rehash` when `eval $(goenv init -)` was previously executed) to skip calling `goenv-rehash` and update shims. +Instead it only updates managed `GOPATH` and `GOROOT` env variables. +It does not attempt to manage when version is `system`. +; Ref: https://github.com/syndbg/goenv/pull/70 + +### Changed + +* Changed `goenv`'s bootstrap (`eval $(goenv init -)`) now to call `goenv-sh-rehash --only-manage-paths`. +This means that it'll export and manage `GOROOT` and `GOPATH` env vars. +It does not attempt to manage when version is `system`. +; Ref: https://github.com/syndbg/goenv/pull/70 + ## 2.0.0beta5 ### Added diff --git a/INSTALL.md b/INSTALL.md index b9598b49..c6f3897c 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -10,7 +10,6 @@ easy to fork and contribute any changes back upstream. $ git clone https://github.com/syndbg/goenv.git ~/.goenv - 2. **Define environment variable `GOENV_ROOT`** to point to the path where goenv repo is cloned and add `$GOENV_ROOT/bin` to your `$PATH` for access to the `goenv` command-line utility. @@ -21,13 +20,13 @@ easy to fork and contribute any changes back upstream. **Zsh note**: Modify your `~/.zshenv` file instead of `~/.bash_profile`. **Ubuntu note**: Modify your `~/.bashrc` file instead of `~/.bash_profile`. -3. **Add `goenv init` to your shell** to enable shims and autocompletion. +3. **Add `goenv init` to your shell** to enable shims, management of `GOPATH` and `GOROOT` and auto-completion. Please make sure `eval "$(goenv init -)"` is placed toward the end of the shell configuration file since it manipulates `PATH` during the initialization. $ echo 'eval "$(goenv init -)"' >> ~/.bash_profile - **Zsh note**: Modify your `~/.zshenv` file instead of `~/.bash_profile`. + **Zsh note**: Modify your `~/.zshenv` or `~/.zshrc` file instead of `~/.bash_profile`. **Ubuntu note**: Modify your `~/.bashrc` file instead of `~/.bash_profile`. **General warning**: There are some systems where the `BASH_ENV` variable is configured @@ -35,19 +34,44 @@ easy to fork and contribute any changes back upstream. `eval "$(goenv init -)` into `.bash_profile`, and **not** into `.bashrc`. Otherwise you may observe strange behaviour, such as `goenv` getting into an infinite loop. See pyenv's issue [#264](https://github.com/yyuu/pyenv/issues/264) for details. + +4. **If you want `goenv` to manage `GOPATH` and `GOROOT` (recommended)**, + add `GOPATH` and `GOROOT` to your shell **after `eval "$(goenv init -)"`**. + + $ echo 'export PATH="$GOROOT/bin:$PATH"' >> ~/.bash_profile + $ echo 'export PATH="$GOPATH/bin:$PATH"' >> ~/.bash_profile + + **Zsh note**: Modify your `~/.zshenv` or `~/.zshrc` file instead of `~/.bash_profile`. + **Ubuntu note**: Modify your `~/.bashrc` file instead of `~/.bash_profile`. + **General warning**: There are some systems where the `BASH_ENV` variable is configured + to point to `.bashrc`. On such systems you should almost certainly put the abovementioned line + `eval "$(goenv init -)` into `.bash_profile`, and **not** into `.bashrc`. Otherwise you + may observe strange behaviour, such as `goenv` getting into an infinite loop. + See pyenv's issue [#264](https://github.com/yyuu/pyenv/issues/264) for details. + -4. **Restart your shell so the path changes take effect.** +5. **Restart your shell so the path changes take effect.** You can now begin using goenv. $ exec $SHELL -5. **Install Go versions into `$GOENV_ROOT/versions`.** - For example, to download and install Go 1.6.2, run: +6. **Install Go versions into `$GOENV_ROOT/versions`.** + For example, to download and install Go 1.12.0, run: - $ goenv install 1.6.2 + $ goenv install 1.12.0 **NOTE:** It downloads and places the prebuilt Go binaries provided by Google. +An example `.zshrc` that is properly configured may look like + +```shell +export GOENV_ROOT="$HOME/.goenv" +export PATH="$GOENV_ROOT/bin:$PATH" +eval "$(goenv init -)" +export PATH="$GOROOT/bin:$PATH" +export PATH="$GOPATH/bin:$PATH" +``` + ## Homebrew on Mac OS X You can also install goenv using the [Homebrew](http://brew.sh) diff --git a/libexec/goenv-exec b/libexec/goenv-exec index 1811653e..44e2ea9f 100755 --- a/libexec/goenv-exec +++ b/libexec/goenv-exec @@ -34,9 +34,39 @@ for script in "${scripts[@]}"; do done shift 1 -# Go needs a GOROOT without system's Go -if [[ $GOENV_VERSION != "system" ]]; then - export GOROOT="$(goenv-prefix)/" + +if [ "${GOENV_VERSION}" != "system" ]; then + case "$shell" in + fish ) + if [ "${GOENV_DISABLE_GOROOT}" != "1" ]; then + set -gx GOROOT "$(goenv-prefix)" + fi + + if [ "${GOENV_DISABLE_GOPATH}" != "1" ]; then + if [ -z "${GOENV_GOPATH_PREFIX}" ]; then + set -gx GOPATH "${HOME}/go/${GOENV_VERSION}" + else + set -gx GOPATH "${GOENV_GOPATH_PREFIX}/${GOENV_VERSION}" + fi + fi + + ;; + * ) + if [ "${GOENV_DISABLE_GOROOT}" != "1" ]; then + export GOROOT="$(goenv-prefix)" + fi + + if [ "${GOENV_DISABLE_GOPATH}" != "1" ]; then + if [ -z "${GOENV_GOPATH_PREFIX}" ]; then + export GOPATH="${HOME}/go/${GOENV_VERSION}" + else + export GOPATH="${GOENV_GOPATH_PREFIX}/${GOENV_VERSION}" + fi + fi + + ;; + esac fi + export PATH="${GOENV_BIN_PATH}:${GOROOT}/bin:${PATH}" exec -a "$GOENV_COMMAND" "$GOENV_COMMAND_PATH" "$@" diff --git a/libexec/goenv-init b/libexec/goenv-init index a46de314..4404380e 100755 --- a/libexec/goenv-init +++ b/libexec/goenv-init @@ -153,3 +153,8 @@ cat </dev/null || true" - ;; -esac +# NOTE: When goenv shell integration is enabled, delegate rehashing of `goenv` shims to goenv-rehash. +# However to speed up `goenv init` and not do rehashing of shims twice, +# allow `only-manage-paths` to skip rehashing of shims. +if [ "$1" != "--only-manage-paths" ]; then + goenv-rehash +fi + +currentVersionName=$(goenv-version-name) + +if [ "${currentVersionName}" != "system" ]; then + case "$shell" in + fish ) + if [ "${GOENV_DISABLE_GOROOT}" != "1" ]; then + echo "set -gx GOROOT \"$(goenv-prefix)\"" + fi + + if [ "${GOENV_DISABLE_GOPATH}" != "1" ]; then + if [ -z "${GOENV_GOPATH_PREFIX}" ]; then + echo "set -gx GOPATH \"${HOME}/go/${currentVersionName}\"" + else + echo "set -gx GOPATH \"${GOENV_GOPATH_PREFIX}/${currentVersionName}\"" + fi + fi + + # NOTE: No rehash support + ;; + * ) + if [ "${GOENV_DISABLE_GOROOT}" != "1" ]; then + echo "export GOROOT=\"$(goenv-prefix)\"" + fi + + if [ "${GOENV_DISABLE_GOPATH}" != "1" ]; then + if [ -z "${GOENV_GOPATH_PREFIX}" ]; then + echo "export GOPATH=\"${HOME}/go/${currentVersionName}\"" + else + echo "export GOPATH=\"${GOENV_GOPATH_PREFIX}/${currentVersionName}\"" + fi + fi + + echo "hash -r 2>/dev/null || true" + ;; + esac +fi diff --git a/test/goenv-exec.bats b/test/goenv-exec.bats index e4b8f6df..3ea41ec6 100644 --- a/test/goenv-exec.bats +++ b/test/goenv-exec.bats @@ -16,8 +16,7 @@ OUT } @test "fails with version that's not installed but specified by GOENV_VERSION" { - export GOENV_VERSION="1.6.1" - run goenv-exec go version + GOENV_VERSION=1.6.1 run goenv-exec go version assert_failure "goenv: version '1.6.1' is not installed (set by GOENV_VERSION environment variable)" } @@ -53,11 +52,10 @@ OUT } @test "completes with names of executables for version that's specified by GOENV_VERSION environment variable" { - export GOENV_VERSION="1.6.1" create_executable "1.6.1" "Zgo123unique" "#!/bin/sh" - goenv-rehash - run goenv-completions exec + GOENV_VERSION=1.6.1 goenv-rehash + GOENV_VERSION=1.6.1 run goenv-completions exec assert_success assert_output < "${GOENV_TEST_DIR}/go-paths" <" { + create_version "1.12.0" + create_executable "1.12.0" "go-paths" <" { + create_version "1.12.0" + create_executable "1.12.0" "go-paths" <" { + create_version "1.12.0" + create_executable "1.12.0" "go-paths" <" { + create_version "1.12.0" + create_executable "1.12.0" "go-paths" <" { + create_version "1.12.0" + create_executable "1.12.0" "go-paths" <" { + create_version "1.12.0" + create_executable "1.12.0" "go-paths" <" { + create_version "1.12.0" + create_executable "1.12.0" "go-paths" <" { + create_version "1.12.0" + create_executable "1.12.0" "go-paths" </dev/null || true" + assert_success +} + +@test "when current set 'version' is not 'system', 'GOENV_DISABLE_GOROOT' is 1, 'GOENV_DISABLE_GOPATH' is 1, shell is 'fish', it does not echo anything" { + export GOENV_SHELL=fish + + create_version "1.12.0" + + GOENV_VERSION=1.12.0 GOENV_DISABLE_GOROOT=1 GOENV_DISABLE_GOPATH=1 run goenv-sh-rehash + + assert_output "" + assert_success +} + +@test "when current set 'version' is not 'system', 'GOENV_DISABLE_GOROOT' is 1, 'GOENV_DISABLE_GOPATH' is 1, shell is 'ksh', it only echoes rehash of binaries" { + export GOENV_SHELL=ksh + + create_version "1.12.0" + + GOENV_VERSION=1.12.0 GOENV_DISABLE_GOROOT=1 GOENV_DISABLE_GOPATH=1 run goenv-sh-rehash + + assert_output "hash -r 2>/dev/null || true" + assert_success +} + +@test "when current set 'version' is not 'system', 'GOENV_DISABLE_GOROOT' is 1, 'GOENV_DISABLE_GOPATH' is 1, shell is 'zsh', it only echoes rehash of binaries" { + export GOENV_SHELL=zsh + + create_version "1.12.0" + + GOENV_VERSION=1.12.0 GOENV_DISABLE_GOROOT=1 GOENV_DISABLE_GOPATH=1 run goenv-sh-rehash + + assert_output "hash -r 2>/dev/null || true" + assert_success +} + +@test "when current set 'version' is not 'system', 'GOENV_DISABLE_GOROOT' is 1, 'GOENV_DISABLE_GOPATH' is 0, shell is 'bash', it echoes export of 'GOPATH' and rehash of binaries" { + export GOENV_SHELL=bash + + create_version "1.12.0" + + GOENV_VERSION=1.12.0 GOENV_DISABLE_GOROOT=1 GOENV_DISABLE_GOPATH=0 run goenv-sh-rehash + assert_output </dev/null || true OUT + assert_success +} + +@test "when current set 'version' is not 'system', 'GOENV_DISABLE_GOROOT' is 1, 'GOENV_DISABLE_GOPATH' is 0, shell is 'ksh', it echoes export of 'GOPATH' and rehash of binaries" { + export GOENV_SHELL=ksh + + create_version "1.12.0" + + GOENV_VERSION=1.12.0 GOENV_DISABLE_GOROOT=1 GOENV_DISABLE_GOPATH=0 run goenv-sh-rehash + assert_output </dev/null || true +OUT assert_success } -@test "resets the binary locations cache when shell is 'zsh'" { +@test "when current set 'version' is not 'system', 'GOENV_DISABLE_GOROOT' is 1, 'GOENV_DISABLE_GOPATH' is 0, shell is 'zsh', it echoes export of 'GOPATH' and rehash of binaries" { export GOENV_SHELL=zsh - run goenv-sh-rehash + + create_version "1.12.0" + + GOENV_VERSION=1.12.0 GOENV_DISABLE_GOROOT=1 GOENV_DISABLE_GOPATH=0 run goenv-sh-rehash + assert_output </dev/null || true OUT + assert_success +} + +@test "when current set 'version' is not 'system', 'GOENV_DISABLE_GOROOT' is 1, 'GOENV_DISABLE_GOPATH' is 0, shell is 'fish', it echoes only export of 'GOPATH'" { + export GOENV_SHELL=fish + + create_version "1.12.0" + + GOENV_VERSION=1.12.0 GOENV_DISABLE_GOROOT=1 GOENV_DISABLE_GOPATH=0 run goenv-sh-rehash + assert_output </dev/null || true OUT + assert_success +} + +@test "when current set 'version' is not 'system', 'GOENV_DISABLE_GOROOT' is 0, 'GOENV_DISABLE_GOPATH' is 0, shell is 'ksh' and 'GOENV_GOPATH_PREFIX' is empty, it echoes export of 'GOROOT', 'GOPATH=\$HOME/go' and rehash of binaries" { + export GOENV_SHELL=ksh + create_version "1.12.0" + + GOENV_VERSION=1.12.0 GOENV_DISABLE_GOROOT=0 GOENV_DISABLE_GOPATH=0 run goenv-sh-rehash + + assert_output </dev/null || true +OUT assert_success } +@test "when current set 'version' is not 'system', 'GOENV_DISABLE_GOROOT' is 0, 'GOENV_DISABLE_GOPATH' is 0, shell is 'zsh' and 'GOENV_GOPATH_PREFIX' is empty, it echoes export of 'GOROOT', 'GOPATH=\$HOME/go' and rehash of binaries" { + export GOENV_SHELL=zsh + + create_version "1.12.0" -@test "does not reset the binary locations cache when shell is 'fish'" { + GOENV_VERSION=1.12.0 GOENV_DISABLE_GOROOT=0 GOENV_DISABLE_GOPATH=0 run goenv-sh-rehash + + assert_output </dev/null || true +OUT + assert_success +} + +@test "when current set 'version' is not 'system', 'GOENV_DISABLE_GOROOT' is 0, 'GOENV_DISABLE_GOPATH' is 0, shell is 'fish' and 'GOENV_GOPATH_PREFIX' is empty, it echoes export of 'GOROOT', 'GOPATH=\$HOME/go'" { export GOENV_SHELL=fish - run goenv-sh-rehash - assert_output '' + + create_version "1.12.0" + + GOENV_VERSION=1.12.0 GOENV_DISABLE_GOROOT=0 GOENV_DISABLE_GOPATH=0 run goenv-sh-rehash + + assert_output <' and rehash of binaries" { + export GOENV_SHELL=bash + + create_version "1.12.0" + + GOENV_GOPATH_PREFIX=/tmp/example GOENV_VERSION=1.12.0 GOENV_DISABLE_GOROOT=0 GOENV_DISABLE_GOPATH=0 run goenv-sh-rehash + + assert_output </dev/null || true OUT + assert_success +} + +@test "when current set 'version' is not 'system', 'GOENV_DISABLE_GOROOT' is 0, 'GOENV_DISABLE_GOPATH' is 0, shell is 'ksh' and 'GOENV_GOPATH_PREFIX' is present, it echoes export of 'GOROOT', 'GOPATH=' and rehash of binaries" { + export GOENV_SHELL=ksh + + create_version "1.12.0" + + GOENV_GOPATH_PREFIX=/tmp/example GOENV_VERSION=1.12.0 GOENV_DISABLE_GOROOT=0 GOENV_DISABLE_GOPATH=0 run goenv-sh-rehash + + assert_output </dev/null || true +OUT + assert_success +} + +@test "when current set 'version' is not 'system', 'GOENV_DISABLE_GOROOT' is 0, 'GOENV_DISABLE_GOPATH' is 0, shell is 'zsh' and 'GOENV_GOPATH_PREFIX' is present, it echoes export of 'GOROOT', 'GOPATH=' and rehash of binaries" { + export GOENV_SHELL=zsh + + create_version "1.12.0" + + GOENV_GOPATH_PREFIX=/tmp/example GOENV_VERSION=1.12.0 GOENV_DISABLE_GOROOT=0 GOENV_DISABLE_GOPATH=0 run goenv-sh-rehash + + assert_output </dev/null || true +OUT + assert_success +} + +@test "when current set 'version' is not 'system', 'GOENV_DISABLE_GOROOT' is 0, 'GOENV_DISABLE_GOPATH' is 0, shell is 'fish' and 'GOENV_GOPATH_PREFIX' is present, it echoes export of 'GOROOT' and 'GOPATH='" { + export GOENV_SHELL=fish + + create_version "1.12.0" + + GOENV_GOPATH_PREFIX=/tmp/example GOENV_VERSION=1.12.0 GOENV_DISABLE_GOROOT=0 GOENV_DISABLE_GOPATH=0 run goenv-sh-rehash + + assert_output <