├── .gitignore ├── LICENSE ├── README.md ├── bin └── goenv └── libexec ├── goenv ├── goenv-exec ├── goenv-global ├── goenv-help ├── goenv-init ├── goenv-install ├── goenv-local ├── goenv-rehash ├── goenv-shell ├── goenv-uninstall ├── goenv-version ├── goenv-version-file ├── goenv-version-file-read └── goenv-versions /.gitignore: -------------------------------------------------------------------------------- 1 | /shims 2 | /version 3 | /versions 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Will Farrington 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # goenv 2 | 3 | rbenv, but for Go. 4 | 5 | ## Installation 6 | 7 | To install the latest stable release: 8 | 9 | ``` 10 | git clone -b v0.0.5 https://github.com/wfarr/goenv.git ~/.goenv 11 | ``` 12 | 13 | Then add the following to your shell config at the end: 14 | 15 | ``` 16 | export PATH="$HOME/.goenv/bin:$PATH" 17 | eval "$(goenv init -)" 18 | ``` 19 | 20 | ## Usage 21 | 22 | ``` 23 | » goenv help 24 | Usage: goenv [] 25 | 26 | Some useful goenv commands are: 27 | exec Execute a command from a particular Go version. 28 | shell Set GOENV_VERSION for the lifetime of a shell. 29 | local Persist the preferred Go version in the cwd. 30 | global Persist the preferred Go default version. 31 | install Install a version of Go. 32 | uninstall Uninstall a version of Go. 33 | version Show the current Go version. 34 | versions Display all versions of Go installed in `${GOENV_ROOT}/versions/*'. 35 | rehash Rehash goenv shims (run this after installing executables) 36 | 37 | See `goenv help ' for information on a specific command. 38 | ``` 39 | 40 | ## Credits 41 | 42 | This library was heavily, heavily, heavily inspired by 43 | [@sstephenson](https://github.com/sstephenson)'s 44 | [rbenv](https://github.com/sstephenson/rbenv) and 45 | [ruby-build](https://github.com/sstephenson/ruby-build) projects. 46 | A few ideas were also taken from [nvm](https://github.com/creationix/nvm). 47 | 48 | A number of patterns and utilities are borrowed from that project, 49 | and it is my hope that goenv provides the same simplicity, 50 | elegance, and usability that I've come to love in rbenv and ruby-build 51 | for Go users. 52 | -------------------------------------------------------------------------------- /bin/goenv: -------------------------------------------------------------------------------- 1 | ./../libexec/goenv -------------------------------------------------------------------------------- /libexec/goenv: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # goenv version 4 | version="0.0.5" 5 | 6 | # Bomb out if we hit an error, ever 7 | set -e 8 | 9 | # Verbose output in debug mode 10 | [ -n "$GOENV_DEBUG" ] && { 11 | set -x 12 | } 13 | 14 | # Helper functions 15 | resolve_link() { 16 | $(type -p greadlink readlink | head -1) "$1" 17 | } 18 | 19 | abs_dirname() { 20 | local cwd="$(pwd)" 21 | local path="$1" 22 | 23 | while [ -n "$path" ]; do 24 | cd "${path%/*}" 25 | local name="${path##*/}" 26 | path="$(resolve_link "$name" || true)" 27 | done 28 | 29 | pwd 30 | cd "$cwd" 31 | } 32 | 33 | # Set up GOENV_ROOT, location where everything lives 34 | 35 | if [ -z "${GOENV_ROOT}" ]; then 36 | GOENV_ROOT="${HOME}/.goenv" 37 | else 38 | GOENV_ROOT="${GOENV_ROOT%/}" 39 | fi 40 | 41 | export GOENV_ROOT 42 | 43 | # Jump into the GOENV_DIR 44 | if [ -z "${GOENV_DIR}" ]; then 45 | GOENV_DIR="$(pwd)" 46 | else 47 | cd "${GOENV_DIR}" 2>/dev/null || { 48 | echo "goenv: cannot change working directory to \`$GOENV_DIR'" 49 | exit 1 50 | } >&2 51 | 52 | GOENV_DIR="$(pwd)" 53 | 54 | cd "$OLDPWD" 55 | fi 56 | 57 | export GOENV_DIR 58 | 59 | # Pop the first argument, our subcommand 60 | command="$1" 61 | 62 | # Make sure we can find out utilities on PATH 63 | bin_path="$(abs_dirname "$0")" 64 | export PATH="${bin_path}":$PATH 65 | 66 | case "$command" in 67 | "" | "-h" | "--help" ) 68 | exec goenv-help 69 | ;; 70 | 71 | "-v" | "--version" ) 72 | echo "goenv ${version}" 73 | exit 74 | ;; 75 | 76 | *) 77 | command_path="${bin_path}/goenv-${command}" 78 | 79 | [ -x "${command_path}" ] || { 80 | echo "goenv: no such command \`$command'" >&2 81 | exit 1 82 | } 83 | 84 | shift 1 85 | exec "goenv-$command" "$@" 86 | ;; 87 | esac 88 | -------------------------------------------------------------------------------- /libexec/goenv-exec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Summary: Execute a command from a particular Go version. 4 | # 5 | # Usage: goenv exec [] 6 | # 7 | # Puts the current Go version onto PATH and runs the specified command. 8 | 9 | # Bomb out if we hit an error, ever 10 | set -e 11 | 12 | # Verbose output in debug mode 13 | [ -n "$GOENV_DEBUG" ] && { 14 | set -x 15 | } 16 | 17 | # Set the current Go version 18 | if [ -z "$GOENV_VERSION" ]; then 19 | GOENV_VERSION="$(goenv version)" 20 | 21 | # Couldn't infer from a file either 22 | if [ -z "$GOENV_VERSION" ]; then 23 | echo "goenv: no \`GOENV_VERSION' configured" >&2 24 | exit 1 25 | fi 26 | fi 27 | 28 | GOROOT="$GOENV_ROOT/versions/$GOENV_VERSION" 29 | 30 | # if the specified Go version lacks this bin, bail 31 | if [ ! -x "$GOROOT/bin/$1" ]; then 32 | echo "goenv: \`$1' does not exist for $GOENV_VERSION" >&2 33 | 34 | for version in "$(goenv versions)"; do 35 | if [ -x "$GOENV_ROOT/versions/$version/bin/$1" ]; then 36 | echo " $version" >&2 37 | fi 38 | done 39 | 40 | exit 1 41 | fi 42 | 43 | export GOENV_VERSION GOROOT 44 | 45 | # Put our bindir onto PATH 46 | export PATH="$GOROOT/bin:$PATH" 47 | 48 | exec "$@" 49 | -------------------------------------------------------------------------------- /libexec/goenv-global: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Summary: Persist the preferred Go default version. 4 | # 5 | # Usage: goenv global 6 | # goenv global --unset|-u 7 | 8 | # Bomb out if we hit an error, ever 9 | set -e 10 | 11 | # Verbose output in debug mode 12 | [ -n "$GOENV_DEBUG" ] && { 13 | set -x 14 | } 15 | 16 | # Set the version 17 | version="$1" 18 | version_file="${GOENV_ROOT}/version" 19 | 20 | case "$version" in 21 | "") 22 | echo "goenv: a version or --unset is required" >&2 23 | exit 1 24 | ;; 25 | 26 | "-u" | "--unset") 27 | if [ -f "$version_file" ]; then 28 | rm "$version_file" 29 | echo "Unset $version_file" 30 | else 31 | echo "goenv: no global version to unset" >&2 32 | exit 1 33 | fi 34 | ;; 35 | 36 | *) 37 | echo "$version" > "$version_file" 38 | echo "Set $version_file to use $version" 39 | ;; 40 | esac 41 | -------------------------------------------------------------------------------- /libexec/goenv-help: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Summary: Display help for a command 4 | # 5 | # Usage: goenv help [--usage] COMMAND 6 | # 7 | # Parses and displays help contents from a command's source file. 8 | # 9 | # A command is considered documented if it starts with a comment block 10 | # that has a `Summary:' or `Usage:' section. Usage instructions can 11 | # span multiple lines as long as subsequent lines are indented. 12 | # The remainder of the comment block is displayed as extended 13 | # documentation. 14 | 15 | # Bomb out if we hit an error, ever 16 | set -e 17 | 18 | # Verbose output in debug mode 19 | [ -n "$GOENV_DEBUG" ] && { 20 | set -x 21 | } 22 | 23 | command_path() { 24 | local command="$1" 25 | command -v goenv-"$command" || command -v goenv-sh-"$command" || true 26 | } 27 | 28 | extract_initial_comment_block() { 29 | sed -ne " 30 | /^#/ !{ 31 | q 32 | } 33 | 34 | s/^#$/# / 35 | 36 | /^# / { 37 | s/^# // 38 | p 39 | } 40 | " 41 | } 42 | 43 | collect_documentation() { 44 | awk ' 45 | /^Summary:/ { 46 | summary = substr($0, 10) 47 | next 48 | } 49 | 50 | /^Usage:/ { 51 | reading_usage = 1 52 | usage = usage "\n" $0 53 | next 54 | } 55 | 56 | /^( *$| )/ && reading_usage { 57 | usage = usage "\n" $0 58 | next 59 | } 60 | 61 | { 62 | reading_usage = 0 63 | help = help "\n" $0 64 | } 65 | 66 | function escape(str) { 67 | gsub(/[`\\$"]/, "\\\\&", str) 68 | return str 69 | } 70 | 71 | function trim(str) { 72 | gsub(/^\n*/, "", str) 73 | gsub(/\n*$/, "", str) 74 | return str 75 | } 76 | 77 | END { 78 | if (usage || summary) { 79 | print "summary=\"" escape(summary) "\"" 80 | print "usage=\"" escape(trim(usage)) "\"" 81 | print "help=\"" escape(trim(help)) "\"" 82 | } 83 | } 84 | ' 85 | } 86 | 87 | documentation_for() { 88 | local filename="$(command_path "$1")" 89 | if [ -n "$filename" ]; then 90 | extract_initial_comment_block < "$filename" | collect_documentation 91 | fi 92 | } 93 | 94 | print_summary() { 95 | local command="$1" 96 | local summary usage help 97 | eval "$(documentation_for "$command")" 98 | 99 | if [ -n "$summary" ]; then 100 | printf " %-9s %s\n" "$command" "$summary" 101 | fi 102 | } 103 | 104 | print_summaries() { 105 | for command; do 106 | print_summary "$command" 107 | done 108 | } 109 | 110 | print_help() { 111 | local command="$1" 112 | local summary usage help 113 | eval "$(documentation_for "$command")" 114 | [ -n "$help" ] || help="$summary" 115 | 116 | if [ -n "$usage" -o -n "$summary" ]; then 117 | if [ -n "$usage" ]; then 118 | echo "$usage" 119 | else 120 | echo "Usage: goenv ${command}" 121 | fi 122 | if [ -n "$help" ]; then 123 | echo 124 | echo "$help" 125 | echo 126 | fi 127 | else 128 | echo "Sorry, this command isn't documented yet." >&2 129 | return 1 130 | fi 131 | } 132 | 133 | print_usage() { 134 | local command="$1" 135 | local summary usage help 136 | eval "$(documentation_for "$command")" 137 | [ -z "$usage" ] || echo "$usage" 138 | } 139 | 140 | unset usage 141 | if [ "$1" = "--usage" ]; then 142 | usage="1" 143 | shift 144 | fi 145 | 146 | if [ -z "$1" ] || [ "$1" == "goenv" ]; then 147 | echo "Usage: goenv []" 148 | [ -z "$usage" ] || exit 149 | echo 150 | echo "Some useful goenv commands are:" 151 | print_summaries exec shell local global install uninstall version versions rehash 152 | echo 153 | echo "See \`goenv help ' for information on a specific command." 154 | else 155 | command="$1" 156 | if [ -n "$(command_path "$command")" ]; then 157 | if [ -n "$usage" ]; then 158 | print_usage "$command" 159 | else 160 | print_help "$command" 161 | fi 162 | else 163 | echo "goenv: no such command \`$command'" >&2 164 | exit 1 165 | fi 166 | fi 167 | -------------------------------------------------------------------------------- /libexec/goenv-init: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Summary: Configure the shell environment for goenv 3 | # Usage: eval "$(goenv init - [])" 4 | 5 | # Bomb out if we hit an error, ever 6 | set -e 7 | 8 | # Verbose output in debug mode 9 | [ -n "$GOENV_DEBUG" ] && { 10 | set -x 11 | } 12 | 13 | # Figure out what we're gonna print 14 | print="" 15 | for args in "$@"; do 16 | if [ "$args" = "-" ]; then 17 | print=1 18 | shift 19 | fi 20 | done 21 | 22 | # Check for a shell 23 | shell="$1" 24 | if [ -z "$shell" ]; then 25 | shell="$(basename "$SHELL")" 26 | fi 27 | 28 | # Helpers to get full path 29 | resolve_link() { 30 | $(type -p greadlink readlink | head -1) $1 31 | } 32 | 33 | abs_dirname() { 34 | local cwd="$(pwd)" 35 | local path="$1" 36 | 37 | while [ -n "$path" ]; do 38 | cd "${path%/*}" 39 | local name="${path##*/}" 40 | path="$(resolve_link "$name" || true)" 41 | done 42 | 43 | pwd 44 | cd "$cwd" 45 | } 46 | 47 | # Set the root of our goenv install 48 | root="$(abs_dirname "$0")/.." 49 | 50 | if [ -z "$print" ]; then 51 | case "$shell" in 52 | bash ) 53 | profile='~/.bash_profile' 54 | ;; 55 | zsh ) 56 | profile='~/.zshrc' 57 | ;; 58 | ksh ) 59 | profile='~/.profile' 60 | ;; 61 | * ) 62 | profile='your profile' 63 | ;; 64 | esac 65 | 66 | { echo "# Load goenv automatically by adding" 67 | echo "# the following to ${profile}:" 68 | echo 69 | echo 'eval "$(goenv init -)"' 70 | echo 71 | } >&2 72 | 73 | exit 1 74 | fi 75 | 76 | mkdir -p "${GOENV_ROOT}/"{shims,versions} 77 | 78 | if [[ ":${PATH}:" != *:"${GOENV_ROOT}/shims":* ]]; then 79 | echo 'export PATH="'${GOENV_ROOT}'/shims:${PATH}"' 80 | fi 81 | 82 | echo 'goenv rehash 2>/dev/null' 83 | -------------------------------------------------------------------------------- /libexec/goenv-install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Summary: Install a version of Go. 3 | # 4 | # Usage: goenv install 5 | # 6 | # Versions should be in the form of N.N.N 7 | 8 | # Bomb out if we hit an error, ever 9 | set -e 10 | 11 | # Verbose output in debug mode 12 | [ -n "$GOENV_DEBUG" ] && { 13 | set -x 14 | } 15 | 16 | # Pull the desired version out of ARGV 17 | version="$1" 18 | version_dir="$GOENV_ROOT/versions/$version" 19 | 20 | # stash the pwd 21 | OLDPWD=$(pwd) 22 | 23 | # Make the version dir and get in there 24 | mkdir -p "$version_dir" 25 | cd "$version_dir" 26 | 27 | platform="$(uname -s | tr '[:upper:]' '[:lower:]')" 28 | 29 | if [ "$(uname -m)" = "x86_64" ]; then 30 | arch="amd64" 31 | else 32 | arch="386" 33 | fi 34 | 35 | if [ "$platform" = "darwin" ]; then 36 | # Since go version 1.2, macOS packages were subdivided into 10.6 and 10.8 37 | # After version 1.4.2, the OS version postfix was dropped 38 | if [ "$version" \> "1.4.2" ]; then 39 | extra="" 40 | elif [ "$version" = "1.2" -o "$version" \> "1.2" -o "$version" \< "1.4.3" ]; then 41 | if [ "$(uname -r)" \> "12" ]; then 42 | extra="-osx10.6" 43 | else 44 | extra="-osx10.6" 45 | fi 46 | fi 47 | fi 48 | 49 | function vercomp () { 50 | # http://stackoverflow.com/questions/4023830 51 | # 0: '=' 52 | # 1: '>' 53 | # 2: '<' 54 | if [[ $1 == $2 ]] 55 | then 56 | echo 0 57 | fi 58 | local IFS=. 59 | local i ver1=($1) ver2=($2) 60 | # fill empty fields in ver1 with zeros 61 | for ((i=${#ver1[@]}; i<${#ver2[@]}; i++)) 62 | do 63 | ver1[i]=0 64 | done 65 | for ((i=0; i<${#ver1[@]}; i++)) 66 | do 67 | if [[ -z ${ver2[i]} ]] 68 | then 69 | # fill empty fields in ver2 with zeros 70 | ver2[i]=0 71 | fi 72 | if ((10#${ver1[i]} > 10#${ver2[i]})) 73 | then 74 | echo 1 75 | fi 76 | if ((10#${ver1[i]} < 10#${ver2[i]})) 77 | then 78 | echo 2 79 | fi 80 | done 81 | # echo 0 82 | } 83 | 84 | download="https://storage.googleapis.com/golang/go${version}.${platform}-${arch}${extra}.tar.gz" 85 | 86 | # Can't get too clever here 87 | set +e 88 | 89 | # Download binary tarball and install 90 | # Linux downloads are formatted differently from OS X 91 | ( 92 | curl --progress -L -f "$download" > "/tmp/go${version}.${platform}-${arch}.tar.gz" && \ 93 | tar zxvf "/tmp/go${version}.${platform}-${arch}.tar.gz" --strip-components 1 && \ 94 | rm "/tmp/go${version}.${platform}-${arch}.tar.gz" 95 | ) || \ 96 | { 97 | cd $OLDPWD 98 | rmdir "$version_dir" 99 | 100 | echo "goenv: unable to install Go \`${version}' from binary, download not available at ${download}" 101 | exit 1 102 | } 103 | 104 | echo "Installed ${version}" 105 | cd $OLDPWD 106 | 107 | exec "${GOENV_ROOT}/bin/goenv" rehash 108 | -------------------------------------------------------------------------------- /libexec/goenv-local: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Summary: Persist the preferred Go version in the cwd. 4 | # 5 | # Usage: goenv local 6 | # goenv local --unset|-u 7 | 8 | # Bomb out if we hit an error, ever 9 | set -e 10 | 11 | # Verbose output in debug mode 12 | [ -n "$GOENV_DEBUG" ] && { 13 | set -x 14 | } 15 | 16 | # Set the version 17 | version="$1" 18 | 19 | case "$version" in 20 | "") 21 | echo "goenv: a version or --unset is required" >&2 22 | exit 1 23 | ;; 24 | 25 | "-u" | "--unset") 26 | if [ -f "$(pwd)/.go-version" ]; then 27 | rm "$(pwd)/.go-version" 28 | echo "Unset local .go-version file" 29 | else 30 | echo "goenv: no local version to unset" >&2 31 | exit 1 32 | fi 33 | ;; 34 | 35 | *) 36 | echo "$version" > "$(pwd)/.go-version" 37 | echo "Created $(pwd)/.go-version with $version" 38 | ;; 39 | esac 40 | -------------------------------------------------------------------------------- /libexec/goenv-rehash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Summary: Rehash goenv shims (run this after installing executables) 3 | 4 | # Bomb out if we hit an error, ever 5 | set -e 6 | 7 | # Verbose output in debug mode 8 | [ -n "$GOENV_DEBUG" ] && { 9 | set -x 10 | } 11 | 12 | # Create the shims directory if it doesn't already exist. 13 | SHIM_PATH="${GOENV_ROOT}/shims" 14 | mkdir -p "$SHIM_PATH" 15 | 16 | # Ensure only one rehash is running at a time 17 | PROTOTYPE_SHIM_PATH="${SHIM_PATH}/.goenv-shim" 18 | 19 | set -o noclobber 20 | { echo > "$PROTOTYPE_SHIM_PATH" 21 | } 2>/dev/null || 22 | { echo "goenv: cannot rehash: $PROTOTYPE_SHIM_PATH exists" 23 | exit 1 24 | } >&2 25 | set +o noclobber 26 | 27 | # Clean up our lockfile if we fail 28 | trap remove_prototype_shim EXIT 29 | 30 | remove_prototype_shim() { 31 | rm -f "$PROTOTYPE_SHIM_PATH" 32 | } 33 | 34 | # Helper to create shim bins 35 | create_prototype_shim() { 36 | cat > "$PROTOTYPE_SHIM_PATH" </dev/null 2>&1; then 75 | for shim in *; do rm -f "$shim"; done 76 | fi 77 | break 78 | done 79 | } 80 | 81 | make_shims() { 82 | local shims="$@" 83 | 84 | for file in $shims; do 85 | local shim="${file##*/}" 86 | register_shim "$shim" 87 | done 88 | } 89 | 90 | # Track registered shims 91 | registered_shims=() 92 | registered_shims_index="" 93 | 94 | # Helper to register a shim 95 | register_shim() { 96 | local shim="$@" 97 | registered_shims["${#registered_shims[@]}"]="$shim" 98 | registered_shims_index="$registered_shims_index/$shim/" 99 | } 100 | 101 | # Helper to install registered shims 102 | install_registered_shims() { 103 | local shim 104 | for shim in "${registered_shims[@]}"; do 105 | [ -e "$shim" ] || ln -f "$PROTOTYPE_SHIM_PATH" "$shim" 106 | done 107 | } 108 | 109 | # Helper to remove stale shims 110 | remove_stale_shims() { 111 | local shim 112 | for shim in *; do 113 | if [[ "$registered_shims_index" != *"/$shim/"* ]]; then 114 | rm -f "$shim" 115 | fi 116 | done 117 | } 118 | 119 | # Change to the shims directory. 120 | cd "$SHIM_PATH" 121 | shopt -s nullglob 122 | 123 | # Create the prototype shim, then register shims for all known 124 | # executables. 125 | create_prototype_shim 126 | remove_outdated_shims 127 | make_shims ../versions/*/bin/* 128 | 129 | # Restore the previous working directory. 130 | cd "$OLDPWD" 131 | 132 | # Change back to the shims directory to install the registered shims 133 | # and remove stale shims. 134 | cd "$SHIM_PATH" 135 | install_registered_shims 136 | remove_stale_shims 137 | -------------------------------------------------------------------------------- /libexec/goenv-shell: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Summary: Set GOENV_VERSION for the lifetime of a shell. 4 | # 5 | # Usage: goenv shell 6 | # goenv shell --unset|-u 7 | 8 | # Bomb out if we hit an error, ever 9 | set -e 10 | 11 | # Verbose output in debug mode 12 | [ -n "$GOENV_DEBUG" ] && { 13 | set -x 14 | } 15 | 16 | version_installed() { 17 | local v="$1" 18 | [ -d "${GOENV_ROOT}/versions/${v}" ] 19 | } 20 | 21 | # Set the version 22 | version="$1" 23 | 24 | case "$version" in 25 | "") 26 | if [ -z "$GOENV_VERSION" ]; then 27 | echo "goenv: no shell version configured" >&2 28 | exit 1 29 | else 30 | echo "echo \"$GOENV_VERSION\"" 31 | fi 32 | ;; 33 | 34 | "-u" | "--unset") 35 | echo "unset GOENV_VERSION" 36 | ;; 37 | 38 | *) 39 | export GOENV_VERSION="$version" 40 | 41 | if version_installed "$version"; then 42 | echo "export GOENV_VERSION=\"${version}\"" 43 | else 44 | echo "goenv: version \`${version}' is not installed" >&2 45 | exit 1 46 | fi 47 | ;; 48 | esac 49 | -------------------------------------------------------------------------------- /libexec/goenv-uninstall: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Summary: Uninstall a version of Go. 3 | # 4 | # Usage: goenv uninstall 5 | # 6 | # Versions should be in the form of N.N.N 7 | 8 | # Bomb out if we hit an error, ever 9 | set -e 10 | 11 | # Verbose output in debug mode 12 | [ -n "$GOENV_DEBUG" ] && { 13 | set -x 14 | } 15 | 16 | # Pull the desired version out of ARGV 17 | version="$1" 18 | version_dir="$GOENV_ROOT/versions/$version" 19 | 20 | if [ -d "$version_dir" ]; then 21 | rm -rf "$version_dir" 22 | echo "Uninstalled $version" 23 | else 24 | echo "goenv: version \`$version' isn't installed" >&2 25 | exit 1 26 | fi 27 | -------------------------------------------------------------------------------- /libexec/goenv-version: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Summary: Show the current Go version. 3 | 4 | # Bomb out if we hit an error, ever 5 | set -e 6 | 7 | # Verbose output in debug mode 8 | [ -n "$GOENV_DEBUG" ] && { 9 | set -x 10 | } 11 | 12 | if [ -z "${GOENV_VERSION}" ]; then 13 | export GOENV_VERSION_FILE="$(goenv-version-file)" 14 | export GOENV_VERSION="$(goenv-version-file-read "$GOENV_VERSION_FILE" || true)" 15 | fi 16 | 17 | version_exists() { 18 | local version="$1" 19 | [ -n "${version}" ] && \ 20 | [ -d "${GOENV_ROOT}/versions/${version}" ] 21 | } 22 | 23 | no_versions() { 24 | [ -z "$(goenv-versions)" ] 25 | } 26 | 27 | if [ -z "$GOENV_VERSION" ]; then 28 | echo "goenv: couldn't find any version specified for use" >&2 29 | exit 1 30 | elif version_exists "$GOENV_VERSION"; then 31 | echo "$GOENV_VERSION" 32 | elif no_versions; then 33 | echo "goenv: no versions of Go are currently installed" >&2 34 | exit 1 35 | else 36 | echo "goenv: version \`$GOENV_VERSION' is not installed" >&2 37 | exit 1 38 | fi 39 | -------------------------------------------------------------------------------- /libexec/goenv-version-file: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Summary: Detect the file that sets the current goenv version 3 | 4 | # Bomb out if we hit an error, ever 5 | set -e 6 | 7 | # Verbose output in debug mode 8 | [ -n "$GOENV_DEBUG" ] && { 9 | set -x 10 | } 11 | 12 | find_local_version_file() { 13 | local root="$1" 14 | while [ -n "$root" ]; do 15 | if [ -e "${root}/.go-version" ]; then 16 | echo "${root}/.go-version" 17 | exit 18 | fi 19 | root="${root%/*}" 20 | done 21 | } 22 | 23 | find_local_version_file "$GOENV_DIR" 24 | [ "$GOENV_DIR" = "$PWD" ] || find_local_version_file "$PWD" 25 | 26 | global_version_file="${GOENV_ROOT}/version" 27 | 28 | if [ -e "$global_version_file" ]; then 29 | echo "$global_version_file" 30 | fi 31 | -------------------------------------------------------------------------------- /libexec/goenv-version-file-read: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Usage: goenv version-file-read 3 | 4 | # Bomb out if we hit an error, ever 5 | set -e 6 | 7 | # Verbose output in debug mode 8 | [ -n "$GOENV_DEBUG" ] && { 9 | set -x 10 | } 11 | 12 | VERSION_FILE="$1" 13 | 14 | if [ -e "$VERSION_FILE" ]; then 15 | # Read the first non-whitespace word from the specified version file. 16 | # Be careful not to load it whole in case there's something crazy in it. 17 | version="" 18 | while read -a words; do 19 | word="${words[0]}" 20 | if [ -z "$version" ] && [ -n "$word" ]; then 21 | version="$word" 22 | fi 23 | done < <( cat "$VERSION_FILE" && echo ) 24 | 25 | if [ -n "$version" ]; then 26 | echo "$version" 27 | exit 28 | fi 29 | fi 30 | 31 | exit 1 32 | -------------------------------------------------------------------------------- /libexec/goenv-versions: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Summary: Display all versions of Go installed in `${GOENV_ROOT}/versions/*'. 3 | 4 | # Bomb out if we hit an error, ever 5 | set -e 6 | 7 | # Verbose output in debug mode 8 | [ -n "$GOENV_DEBUG" ] && { 9 | set -x 10 | } 11 | 12 | # Iterate over installed versions and write to output 13 | for path in "${GOENV_ROOT}/versions/"*; do 14 | if [ -d "$path" ]; then 15 | echo "${path##*/}" 16 | fi 17 | done 18 | --------------------------------------------------------------------------------