From 258e4413b165b87e4c0c3190b45c1a167678b4d5 Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Wed, 27 May 2015 23:10:39 -0400 Subject: [PATCH 1/5] create hook: version-name Expose a `version-name` hook. It is invoked *after* the traditional `RBENV_VERSION` lookup. Which means hook scripts can interrogate `$RBENV_VERSION_FILE` and/or `$RBENV_VERSION` (or use the executables). The hooks are then run, giving plugins a chance to alter `RBENV_VERSION`. Once the hooks have run, we now have (in `$RBENV_VERSION`) the actual version we want to use (or it's empty which defaults to `system` per normal). Lastly, the same logic remains for checking if the version exists, or trimming the `ruby-` prefix. Prime example: the ruby-bundler-ruby-version plugin can select a ruby by using the `ruby` directive from the `Gemfile` if a local `.ruby-version` doesn't exist. --- libexec/rbenv-version-name | 7 +++++++ test/version-name.bats | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/libexec/rbenv-version-name b/libexec/rbenv-version-name index 3769a7cd..1af277bf 100755 --- a/libexec/rbenv-version-name +++ b/libexec/rbenv-version-name @@ -8,6 +8,13 @@ if [ -z "$RBENV_VERSION" ]; then RBENV_VERSION="$(rbenv-version-file-read "$RBENV_VERSION_FILE" || true)" fi +OLDIFS="$IFS" +IFS=$'\n' scripts=(`rbenv-hooks version-name`) +IFS="$OLDIFS" +for script in "${scripts[@]}"; do + source "$script" +done + if [ -z "$RBENV_VERSION" ] || [ "$RBENV_VERSION" = "system" ]; then echo "system" exit diff --git a/test/version-name.bats b/test/version-name.bats index d6438b5b..bc633121 100644 --- a/test/version-name.bats +++ b/test/version-name.bats @@ -2,6 +2,13 @@ load test_helper +export RBENV_HOOK_PATH="${RBENV_ROOT}/rbenv.d" + +create_hook() { + mkdir -p "${RBENV_ROOT}/rbenv.d/version-name" + cat > "${RBENV_ROOT}/rbenv.d/version-name/$1" <<<"$2" +} + create_version() { mkdir -p "${RBENV_ROOT}/versions/$1" } @@ -22,6 +29,18 @@ setup() { assert_success "system" } +@test "RBENV_VERSION can be overridden by hook" { + create_version "1.8.7" + create_version "1.9.3" + + RBENV_VERSION=1.8.7 run rbenv-version-name + assert_success "1.8.7" + + create_hook test.bash "RBENV_VERSION=1.9.3" + RBENV_VERSION=1.8.7 run rbenv-version-name + assert_success "1.9.3" +} + @test "RBENV_VERSION has precedence over local" { create_version "1.8.7" create_version "1.9.3" From c3a5f91ed0d9f7a0382ae1821297051bc827e4b8 Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Wed, 27 May 2015 23:29:11 -0400 Subject: [PATCH 2/5] create hook: version-origin Expose a `version-origin` hook. It is invoked *before* the traditional `rbenv-version-file` lookup. Because `version-origin` is traditionally run immediately after `version-name`, then any plugin hooks that alter `version-name` would have done so. Thus, running `version-origin` prior to printing the origin gives those plugins a chance to alter the `version-origin` to match. If any of the hooks set `$RBENV_VERSION_ORIGIN`, then it is used as the return value. Otherwise, the existing logic continues to return "environment variable" or "filename" as appropriate. This change, in conjunction with the `version-name` hook, makes a clean seam by which plugins can inject their own ruby version setting logic. Using this seam, as opposed to altering `$RBENV_COMMAND_PATH` from the `which` hook, means that the version name and origin are set more reliably and so `version`, `version-name`, `version-origin` and `which` all work as expected. Indeed, even PS1 works now. --- libexec/rbenv-version-origin | 11 ++++++++++- test/version-origin.bats | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/libexec/rbenv-version-origin b/libexec/rbenv-version-origin index ae7abf9c..a9d21c4c 100755 --- a/libexec/rbenv-version-origin +++ b/libexec/rbenv-version-origin @@ -3,7 +3,16 @@ set -e [ -n "$RBENV_DEBUG" ] && set -x -if [ -n "$RBENV_VERSION" ]; then +OLDIFS="$IFS" +IFS=$'\n' scripts=(`rbenv-hooks version-origin`) +IFS="$OLDIFS" +for script in "${scripts[@]}"; do + source "$script" +done + +if [ -n "$RBENV_VERSION_ORIGIN" ]; then + echo "$RBENV_VERSION_ORIGIN" +elif [ -n "$RBENV_VERSION" ]; then echo "RBENV_VERSION environment variable" else rbenv-version-file diff --git a/test/version-origin.bats b/test/version-origin.bats index 8ad4db04..fed0aaa5 100644 --- a/test/version-origin.bats +++ b/test/version-origin.bats @@ -2,6 +2,13 @@ load test_helper +export RBENV_HOOK_PATH="${RBENV_ROOT}/rbenv.d" + +create_hook() { + mkdir -p "${RBENV_ROOT}/rbenv.d/version-origin" + cat > "${RBENV_ROOT}/rbenv.d/version-origin/$1" <<<"$2" +} + setup() { mkdir -p "$RBENV_TEST_DIR" cd "$RBENV_TEST_DIR" @@ -36,3 +43,12 @@ setup() { run rbenv-version-origin assert_success "${PWD}/.rbenv-version" } + +@test "reports from hook" { + touch .ruby-version + create_hook test.bash "RBENV_VERSION_ORIGIN=plugin" + + RBENV_VERSION=1 run rbenv-version-origin + + assert_success "plugin" +} From 97f0499f43a1a885beea2c738a179175ecc48580 Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Fri, 6 Nov 2015 21:17:40 -0500 Subject: [PATCH 3/5] add version-name/version-origin to hooks completion --- libexec/rbenv-hooks | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libexec/rbenv-hooks b/libexec/rbenv-hooks index 201c91da..df0a6f60 100755 --- a/libexec/rbenv-hooks +++ b/libexec/rbenv-hooks @@ -9,6 +9,8 @@ set -e if [ "$1" = "--complete" ]; then echo exec echo rehash + echo version-name + echo version-origin echo which exit fi From 4fde4ecbaf1e1f3082c9275a6f244c70527ad497 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Wed, 23 Dec 2015 17:26:53 +0100 Subject: [PATCH 4/5] Ensure RBENV_VERSION_ORIGIN is not inherited from environment It's only supposed to be set from `version-origin` hooks, but not inherited from environment in case it was set. --- libexec/rbenv-version-origin | 2 ++ test/version-origin.bats | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/libexec/rbenv-version-origin b/libexec/rbenv-version-origin index a9d21c4c..3f1d4f03 100755 --- a/libexec/rbenv-version-origin +++ b/libexec/rbenv-version-origin @@ -3,6 +3,8 @@ set -e [ -n "$RBENV_DEBUG" ] && set -x +unset RBENV_VERSION_ORIGIN + OLDIFS="$IFS" IFS=$'\n' scripts=(`rbenv-hooks version-origin`) IFS="$OLDIFS" diff --git a/test/version-origin.bats b/test/version-origin.bats index fed0aaa5..e0576648 100644 --- a/test/version-origin.bats +++ b/test/version-origin.bats @@ -52,3 +52,8 @@ setup() { assert_success "plugin" } + +@test "doesn't inherit RBENV_VERSION_ORIGIN from environment" { + RBENV_VERSION_ORIGIN=ignored run rbenv-version-origin + assert_success "${RBENV_ROOT}/version" +} From 6e300322789b7809cb70a97948dd19c163b02a1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Wed, 23 Dec 2015 17:32:21 +0100 Subject: [PATCH 5/5] Simplify version-name, version-origin hook tests No need for helper function that's gonna be used just once. --- test/version-name.bats | 16 +++++----------- test/version-origin.bats | 16 +++++----------- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/test/version-name.bats b/test/version-name.bats index ef283283..82e1b2d0 100644 --- a/test/version-name.bats +++ b/test/version-name.bats @@ -2,13 +2,6 @@ load test_helper -export RBENV_HOOK_PATH="${RBENV_ROOT}/rbenv.d" - -create_hook() { - mkdir -p "${RBENV_ROOT}/rbenv.d/version-name" - cat > "${RBENV_ROOT}/rbenv.d/version-name/$1" <<<"$2" -} - create_version() { mkdir -p "${RBENV_ROOT}/versions/$1" } @@ -33,11 +26,12 @@ setup() { create_version "1.8.7" create_version "1.9.3" - RBENV_VERSION=1.8.7 run rbenv-version-name - assert_success "1.8.7" + mkdir -p "${RBENV_ROOT}/rbenv.d/version-name" + cat > "${RBENV_ROOT}/rbenv.d/version-name/test.bash" < "${RBENV_ROOT}/rbenv.d/version-origin/$1" <<<"$2" -} - setup() { mkdir -p "$RBENV_TEST_DIR" cd "$RBENV_TEST_DIR" @@ -45,11 +38,12 @@ setup() { } @test "reports from hook" { - touch .ruby-version - create_hook test.bash "RBENV_VERSION_ORIGIN=plugin" - - RBENV_VERSION=1 run rbenv-version-origin + mkdir -p "${RBENV_ROOT}/rbenv.d/version-origin" + cat > "${RBENV_ROOT}/rbenv.d/version-origin/test.bash" <