From edde7ce995f5e48d5ec579bb8557e0715b98811a Mon Sep 17 00:00:00 2001 From: NUAAwqy <146524024+NUAAwqy@users.noreply.github.com> Date: Thu, 29 Oct 2026 17:46:35 +0000 Subject: [PATCH] [Refactor] `install.sh`: check profile lines through one comment-aware helper `nvm_do_install` checked for its `nvm.sh` and `bash_completion` source lines with two separate regexes that each had to skip commented-out lines. Move that into `nvm_profile_has_line`, which strips whole-line comments before matching, and test the `bash_completion` line and an already set up profile too. --- install.sh | 11 ++- .../nvm_install_profile_commented | 93 +++++++++++++++++++ 2 files changed, 101 insertions(+), 3 deletions(-) create mode 100755 test/install_script/nvm_install_profile_commented diff --git a/install.sh b/install.sh index a83fe041..51654f4d 100755 --- a/install.sh +++ b/install.sh @@ -48,6 +48,11 @@ nvm_latest_version() { nvm_echo "v0.40.8" } +nvm_profile_has_line() { + # a commented-out line sources nothing, so it must not count as already present + command sed 's/^[[:space:]]*#.*//' "$1" | nvm_grep -q "$2" +} + nvm_profile_is_bash_or_zsh() { local TEST_PROFILE TEST_PROFILE="${1-}" @@ -527,14 +532,14 @@ nvm_do_install() { if nvm_profile_is_bash_or_zsh "${NVM_PROFILE-}"; then BASH_OR_ZSH=true fi - if ! command grep -qc '^[[:space:]]*[^#[:space:]].*/nvm\.sh' "$NVM_PROFILE"; then + if ! nvm_profile_has_line "${NVM_PROFILE}" '/nvm.sh'; then nvm_echo "=> Appending nvm source string to $NVM_PROFILE" command printf '%b' "${SOURCE_STR}" >> "$NVM_PROFILE" else nvm_echo "=> nvm source string already in ${NVM_PROFILE}" fi # shellcheck disable=SC2016 - if ${BASH_OR_ZSH} && ! command grep -qc '^[[:space:]]*[^#[:space:]].*\$NVM_DIR/bash_completion' "$NVM_PROFILE"; then + if ${BASH_OR_ZSH} && ! nvm_profile_has_line "${NVM_PROFILE}" '$NVM_DIR/bash_completion'; then nvm_echo "=> Appending bash_completion source string to $NVM_PROFILE" if [ -n "$(command tail -c 1 "$NVM_PROFILE")" ]; then nvm_echo >> "$NVM_PROFILE" @@ -574,7 +579,7 @@ nvm_reset() { unset -f nvm_has nvm_has_executable nvm_install_dir nvm_latest_version nvm_profile_is_bash_or_zsh \ nvm_source nvm_node_version nvm_download install_nvm_from_git nvm_install_node \ install_nvm_as_script nvm_try_profile nvm_detect_profile nvm_is_wsl nvm_check_global_modules \ - nvm_do_install nvm_reset nvm_default_install_dir nvm_grep + nvm_do_install nvm_reset nvm_default_install_dir nvm_grep nvm_profile_has_line } [ "_$NVM_ENV" = "_testing" ] || nvm_do_install diff --git a/test/install_script/nvm_install_profile_commented b/test/install_script/nvm_install_profile_commented new file mode 100755 index 00000000..9d1d8f42 --- /dev/null +++ b/test/install_script/nvm_install_profile_commented @@ -0,0 +1,93 @@ +#!/bin/sh + +NVM_TEST_DIR='' +NVM_PROFILE_PATH='' + +die () { echo "$@" ; cleanup ; exit 1; } + +cleanup() { + if [ -n "${NVM_TEST_DIR}" ] && [ -d "${NVM_TEST_DIR}" ]; then + rm -rf "${NVM_TEST_DIR}" + fi + unset -f install_nvm_from_git install_nvm_as_script nvm_detect_profile nvm_has + unset -f setup cleanup die make_profile run_install + unset NVM_ENV METHOD PROFILE NVM_DIR NVM_TEST_DIR NVM_PROFILE_PATH +} + +setup() { + NVM_ENV=testing \. ../../install.sh + + # Mock installation functions to do nothing + install_nvm_from_git() { :; } + install_nvm_as_script() { :; } + + # Mock nvm_has to return true for git (to take the git path) + nvm_has() { + case "$1" in + git) return 0 ;; + *) return 1 ;; + esac + } + + # Mock nvm_detect_profile to point at the profile under test + nvm_detect_profile() { + nvm_echo "${NVM_PROFILE_PATH}" + } +} + +make_profile() { + printf '%s\n' "$@" > "${NVM_PROFILE_PATH}" +} + +run_install() { + PROFILE='' METHOD='' NVM_DIR="${NVM_TEST_DIR}/nvm" nvm_do_install 2>&1 +} + +setup + +NVM_TEST_DIR="$(mktemp -d)" || die 'unable to make the test dir' +mkdir -p "${NVM_TEST_DIR}/nvm" || die 'unable to make the install dir' +touch "${NVM_TEST_DIR}/nvm/nvm.sh" || die 'unable to make an empty nvm.sh' +NVM_PROFILE_PATH="${NVM_TEST_DIR}/.bashrc" + +# +# Test: a commented-out nvm.sh line does not load nvm, so the source string is still appended +# + +make_profile 'export NVM_DIR="$HOME/.nvm"' '# [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm' ' # [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' +OUTPUT="$(run_install)" +case "${OUTPUT}" in + *"Appending nvm source string"*) ;; + *) die "a commented-out nvm.sh line should not count as the source string; got: ${OUTPUT}" ;; +esac +grep -q '^\[ -s "$NVM_DIR/nvm.sh"' "${NVM_PROFILE_PATH}" || die "the source string was not appended to the profile: $(cat "${NVM_PROFILE_PATH}")" + +# +# Test: the same for a commented-out bash_completion line in a bash profile +# + +make_profile '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm' '# [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion' +OUTPUT="$(run_install)" +case "${OUTPUT}" in + *"nvm source string already in"*) ;; + *) die "an active nvm.sh line should still count as the source string; got: ${OUTPUT}" ;; +esac +case "${OUTPUT}" in + *"Appending bash_completion source string"*) ;; + *) die "a commented-out bash_completion line should not count; got: ${OUTPUT}" ;; +esac + +# +# Test: with both lines active, the profile is left alone +# + +make_profile 'export NVM_DIR="$HOME/.nvm"' '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm' '[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion' +BEFORE="$(cat "${NVM_PROFILE_PATH}")" +OUTPUT="$(run_install)" +case "${OUTPUT}" in + *"nvm source string already in"*"bash_completion source string already in"*) ;; + *) die "an active profile should not be touched; got: ${OUTPUT}" ;; +esac +[ "_$(cat "${NVM_PROFILE_PATH}")" = "_${BEFORE}" ] || die "the profile was changed: $(cat "${NVM_PROFILE_PATH}")" + +cleanup