From e8e5f89098b964c8f26a49ef7e4866479b5c9faa Mon Sep 17 00:00:00 2001 From: Ian MacLeod Date: Mon, 4 Sep 2017 11:19:52 -0700 Subject: [PATCH 1/3] Introduce NVM_PREFER_LOCAL_BINS Prepends `$(npm bin)` on `$PATH` whenever cding into directories with `package.json` (or anywhere up the tree) --- README.md | 11 +++++++++++ zsh-nvm.plugin.zsh | 24 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/README.md b/README.md index 3899b8a..88f71be 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,17 @@ export NVM_AUTO_USE=true antigen bundle lukechilds/zsh-nvm ``` +### Local bins + +If your projects include dependencies with binaries, this ensures that they take precedence on your `$PATH` over globally installed ones. + +For example, if you are using antigen, you would put the following in your `.zshrc`: + +```shell +export NVM_PREFER_LOCAL_BINS=true +antigen bundle lukechilds/zsh-nvm +``` + ## Installation ### Using [Antigen](https://github.com/zsh-users/antigen) diff --git a/zsh-nvm.plugin.zsh b/zsh-nvm.plugin.zsh index 83967b7..68ec0fd 100644 --- a/zsh-nvm.plugin.zsh +++ b/zsh-nvm.plugin.zsh @@ -195,6 +195,27 @@ _zsh_nvm_install_wrapper() { esac } +_zsh_nvm_add_local_bin_path() { + local nearest_package=$(nvm_find_up package.json) + # Skip if we're moving within a project (npm bin is slow). + # + # Also notice that we prepend a value in front of the variable so that it + # isn't expanded by %~ prompts. + [[ "z$nearest_package" == "$NVM_CURRENT_PACKAGE_PATH" ]] && return + NVM_CURRENT_PACKAGE_PATH=z$nearest_package + + # Ensure a clean slate; so that we are not prepending paths forever. + if [[ -n "$NVM_PATH_WITHOUT_LOCAL_BINS" ]]; then + PATH=$NVM_PATH_WITHOUT_LOCAL_BINS + unset NVM_PATH_WITHOUT_LOCAL_BINS + fi + + if [[ -n "$nearest_package" ]]; then + NVM_PATH_WITHOUT_LOCAL_BINS=$PATH + PATH=$(npm bin):$PATH + fi +} + # Don't init anything if this is true (debug/testing only) if [[ "$ZSH_NVM_NO_LOAD" != true ]]; then @@ -209,6 +230,9 @@ if [[ "$ZSH_NVM_NO_LOAD" != true ]]; then # Auto use nvm on chpwd [[ "$NVM_AUTO_USE" == true ]] && add-zsh-hook chpwd _zsh_nvm_auto_use && _zsh_nvm_auto_use + + # Ensure that local bins take precedence on $PATH. + [[ "$NVM_PREFER_LOCAL_BINS" == true ]] && add-zsh-hook chpwd _zsh_nvm_add_local_bin_path && _zsh_nvm_add_local_bin_path fi fi From a04d4e5e8055c3bd0b775c63eb8076ba5f58929b Mon Sep 17 00:00:00 2001 From: Ian MacLeod Date: Mon, 4 Sep 2017 11:58:01 -0700 Subject: [PATCH 2/3] Tests for NVM_PREFER_LOCAL_BINS --- tests/options/NVM_PREFER_LOCAL_BINS | 41 +++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100755 tests/options/NVM_PREFER_LOCAL_BINS diff --git a/tests/options/NVM_PREFER_LOCAL_BINS b/tests/options/NVM_PREFER_LOCAL_BINS new file mode 100755 index 0000000..4718fc6 --- /dev/null +++ b/tests/options/NVM_PREFER_LOCAL_BINS @@ -0,0 +1,41 @@ +#!/bin/sh +source ../common.sh + +# Setup projects in tmp, so we don't have ancestor paths of this repo messing +# with things. +cd $(mktemp -d) +# npm bin can resolve to a different path (/private/var instead of /var) on some +# platforms. It also resolves to the current directory if there is no +# package.json up the current path. So, we use it to expand our path. +sandbox=$(dirname $(dirname $(npm bin))) +echo "Running NVM_PREFER_LOCAL_BINS in $sandbox\n" + +mkdir -p package/src/a/b +touch package/package.json +mkdir -p package/vendor +touch package/vendor/package.json + +# Load it. +export NVM_PREFER_LOCAL_BINS=true +load_zsh_nvm +# This is our base path, without any local binary paths in it. +base_path=$PATH + +# Check cd directly into a package directory +cd ./package +[[ "$PATH" == "$sandbox/package/node_modules/.bin:$base_path" ]] || die "Didn't prepend local bin dir to path when moving into package directory" + +# Check package subdirs +cd ./src +cd ./a +cd ./b +[[ "$PATH" == "$sandbox/package/node_modules/.bin:$base_path" ]] || die "Didn't prepend local bin dir to path when moving into package subdirectories" + +# Check nested packages +cd ../../.. +cd ./vendor +[[ "$PATH" == "$sandbox/package/vendor/node_modules/.bin:$base_path" ]] || die "Didn't prepend local bin dir to path when moving into a nested package" + +# Check leaving +cd ../.. +[[ "$PATH" == "$base_path" ]] || die "Didn't remove local bin dir when leaving a package directory" From 7830783ce9b28dbb3fff4a3dcdee75c673a1d9e6 Mon Sep 17 00:00:00 2001 From: Ian MacLeod Date: Mon, 4 Sep 2017 12:13:50 -0700 Subject: [PATCH 3/3] Make sure that it handles cases where there is no global node install --- tests/options/NVM_PREFER_LOCAL_BINS | 19 ++++++++++++++----- zsh-nvm.plugin.zsh | 1 + 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/tests/options/NVM_PREFER_LOCAL_BINS b/tests/options/NVM_PREFER_LOCAL_BINS index 4718fc6..0a886a7 100755 --- a/tests/options/NVM_PREFER_LOCAL_BINS +++ b/tests/options/NVM_PREFER_LOCAL_BINS @@ -4,11 +4,7 @@ source ../common.sh # Setup projects in tmp, so we don't have ancestor paths of this repo messing # with things. cd $(mktemp -d) -# npm bin can resolve to a different path (/private/var instead of /var) on some -# platforms. It also resolves to the current directory if there is no -# package.json up the current path. So, we use it to expand our path. -sandbox=$(dirname $(dirname $(npm bin))) -echo "Running NVM_PREFER_LOCAL_BINS in $sandbox\n" +echo "Running NVM_PREFER_LOCAL_BINS in $(pwd)\n" mkdir -p package/src/a/b touch package/package.json @@ -18,8 +14,21 @@ touch package/vendor/package.json # Load it. export NVM_PREFER_LOCAL_BINS=true load_zsh_nvm + +# Check cding without node installed (shouldn't fail) +cd ./package +cd ./src/a/b +cd ../../../.. + +# Now test with node installed +nvm install 8 +nvm use 8 # This is our base path, without any local binary paths in it. base_path=$PATH +# npm bin can resolve to a different path (/private/var instead of /var) on some +# platforms. It also resolves to the current directory if there is no +# package.json up the current path. So, we use it to expand our path. +sandbox=$(dirname $(dirname $(npm bin))) # Check cd directly into a package directory cd ./package diff --git a/zsh-nvm.plugin.zsh b/zsh-nvm.plugin.zsh index 68ec0fd..ee35705 100644 --- a/zsh-nvm.plugin.zsh +++ b/zsh-nvm.plugin.zsh @@ -196,6 +196,7 @@ _zsh_nvm_install_wrapper() { } _zsh_nvm_add_local_bin_path() { + _zsh_nvm_has npm || return # No-op until we have a copy of node in our env. local nearest_package=$(nvm_find_up package.json) # Skip if we're moving within a project (npm bin is slow). #