From c6bf252f7d39e03ac48ca9a8e5887b82b6710178 Mon Sep 17 00:00:00 2001 From: NUAAwqy <146524024+NUAAwqy@users.noreply.github.com> Date: Thu, 29 Oct 2026 14:59:29 +0000 Subject: [PATCH] [Fix] `ls`: list versions whose directory is a symlink nvm_ls collects installed versions with `find /* -name . -o -type d -prune -o -path ...`, and `-type d` is false for a symlink, so a version dir that links to another volume was skipped from the listing entirely - while `nvm version`, `nvm which` and `nvm use` all kept working on it. Have that find follow symlinks, which makes linked-in versions visible and still ignores a broken link. Fixes #617. --- nvm.sh | 2 +- ...ng 'nvm ls' should list symlinked versions | 27 +++++++++++++++++++ test/fast/Listing versions/teardown | 1 + 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100755 test/fast/Listing versions/Running 'nvm ls' should list symlinked versions diff --git a/nvm.sh b/nvm.sh index 22024257..0011b517 100755 --- a/nvm.sh +++ b/nvm.sh @@ -2516,7 +2516,7 @@ nvm_ls() { NVM_DIR_SED="$(nvm_echo "${NVM_DIR}" | command sed 's/[][\.*^$#]/\\&/g')" local NVM_VERSION_DIR_IOJS_SED NVM_VERSION_DIR_IOJS_SED="$(nvm_echo "${NVM_VERSION_DIR_IOJS}" | command sed 's/[][\.*^$#]/\\&/g')" - VERSIONS="$(command find "${NVM_DIRS_TO_SEARCH1}"/* "${NVM_DIRS_TO_SEARCH2}"/* "${NVM_DIRS_TO_SEARCH3}"/* -name . -o -type d -prune -o -path "${PATTERN}*" \ + VERSIONS="$(command find -L "${NVM_DIRS_TO_SEARCH1}"/* "${NVM_DIRS_TO_SEARCH2}"/* "${NVM_DIRS_TO_SEARCH3}"/* -name . -o -type d -prune -o -path "${PATTERN}*" \ | command sed -e " s#${NVM_VERSION_DIR_IOJS_SED}/#versions/${NVM_IOJS_PREFIX}/#; s#^${NVM_DIR_SED}/##; diff --git a/test/fast/Listing versions/Running 'nvm ls' should list symlinked versions b/test/fast/Listing versions/Running 'nvm ls' should list symlinked versions new file mode 100755 index 00000000..728b915a --- /dev/null +++ b/test/fast/Listing versions/Running 'nvm ls' should list symlinked versions @@ -0,0 +1,27 @@ +#!/bin/sh + +: nvm.sh +\. ../../../nvm.sh +\. ../../common.sh + +die () { echo "$@" ; exit 1; } + +make_fake_node v0.0.1 || die 'unable to make a fake node' + +# a version that lives outside of NVM_DIR and is linked in, which is how some +# users keep their versions on a separate volume +REAL_DIR="$(cd ../../.. && pwd)/symlink-target" +rm -rf "${REAL_DIR}" +mkdir -p "${REAL_DIR}/v0.0.2/bin" || die 'unable to make the link target dir' +make_echo "${REAL_DIR}/v0.0.2/bin/node" v0.0.2 || die 'unable to make fake node bin' +rm -f "$(nvm_version_path v0.0.2)" +ln -s "${REAL_DIR}/v0.0.2" "$(nvm_version_path v0.0.2)" || die 'unable to symlink the version dir' + +nvm ls | grep v0.0.1 >/dev/null || die "v0.0.1 not found in: $(nvm ls)" +nvm ls | grep v0.0.2 >/dev/null || die "the symlinked v0.0.2 not found in: $(nvm ls)" +nvm ls 0.0 | grep v0.0.2 >/dev/null || die "the symlinked v0.0.2 not found with a pattern in: $(nvm ls 0.0)" +nvm ls 0.0.2 | grep v0.0.2 >/dev/null || die "the symlinked v0.0.2 not found with an exact version in: $(nvm ls 0.0.2)" + +# leave no trace, so the tests that compare `nvm ls` output verbatim are unaffected +rm -f "$(nvm_version_path v0.0.2)" +rm -rf "${REAL_DIR}" diff --git a/test/fast/Listing versions/teardown b/test/fast/Listing versions/teardown index eb9610ba..d6c4e281 100755 --- a/test/fast/Listing versions/teardown +++ b/test/fast/Listing versions/teardown @@ -14,3 +14,4 @@ rm -rf ../../../v0.20.3 rm -rf ../../../versions rm -f ../../../alias/stable rm -f ../../../alias/unstable +rm -rf ../../../symlink-target