Skip to content

Commit 499d303

Browse files
committed
[Perf] use/nvm_die_on_prefix: replicate npm config algorithm and remove npm config call
1 parent 31bc0a1 commit 499d303

File tree

2 files changed

+174
-41
lines changed

2 files changed

+174
-41
lines changed

nvm.sh

Lines changed: 69 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2180,6 +2180,15 @@ nvm_npm_global_modules() {
21802180
nvm_echo "${INSTALLS} //// ${LINKS}"
21812181
}
21822182

2183+
nvm_npmrc_bad_news_bears() {
2184+
local NVM_NPMRC
2185+
NVM_NPMRC="${1-}"
2186+
if [ -n "${NVM_NPMRC}" ] && [ -f "${NVM_NPMRC}" ] && nvm_grep -Ee '^(prefix|globalconfig) *=' <"${NVM_NPMRC}" >/dev/null; then
2187+
return 0
2188+
fi
2189+
return 1
2190+
}
2191+
21832192
nvm_die_on_prefix() {
21842193
local NVM_DELETE_PREFIX
21852194
NVM_DELETE_PREFIX="${1-}"
@@ -2227,29 +2236,70 @@ nvm_die_on_prefix() {
22272236
fi
22282237
fi
22292238

2230-
if ! nvm_has 'npm'; then
2231-
return
2239+
# here, npm config checks npmrc files.
2240+
# the stack is: cli, env, project, user, global, builtin, defaults
2241+
# cli does not apply; env is covered above, defaults don't exist for prefix
2242+
# there are 4 npmrc locations to check: project, global, user, and builtin
2243+
# project: find the closest node_modules or package.json-containing dir, `.npmrc`
2244+
# global: default prefix + `/etc/npmrc`
2245+
# user: $HOME/.npmrc
2246+
# builtin: npm install location, `npmrc`
2247+
#
2248+
# if any of them have a `prefix`, fail.
2249+
# if any have `globalconfig`, fail also, just in case, to avoid spidering configs.
2250+
2251+
local NVM_NPM_BUILTIN_NPMRC
2252+
NVM_NPM_BUILTIN_NPMRC="${NVM_VERSION_DIR}/lib/node_modules/npm/npmrc"
2253+
if nvm_npmrc_bad_news_bears "${NVM_NPM_BUILTIN_NPMRC}"; then
2254+
if [ "_${NVM_DELETE_PREFIX}" = "_1" ]; then
2255+
npm config --loglevel=warn delete prefix --userconfig="${NVM_NPM_BUILTIN_NPMRC}"
2256+
npm config --loglevel=warn delete globalconfig --userconfig="${NVM_NPM_BUILTIN_NPMRC}"
2257+
else
2258+
nvm_err "Your builtin npmrc file ($(nvm_sanitize_path "${NVM_NPM_BUILTIN_NPMRC}"))"
2259+
nvm_err 'has a `globalconfig` and/or a `prefix` setting, which are incompatible with nvm.'
2260+
nvm_err "Run \`${NVM_COMMAND}\` to unset it."
2261+
return 10
2262+
fi
22322263
fi
22332264

2234-
local NVM_NPM_PREFIX
2235-
local NVM_OS
2236-
NVM_OS="$(nvm_get_os)"
2237-
NVM_NPM_PREFIX="$(npm config --loglevel=warn get prefix)"
2238-
if [ ! "${NVM_VERSION_DIR}" -ef "${NVM_NPM_PREFIX}" ] && ! (nvm_tree_contains_path "${NVM_VERSION_DIR}" "${NVM_NPM_PREFIX}" >/dev/null 2>&1); then
2265+
local NVM_NPM_GLOBAL_NPMRC
2266+
NVM_NPM_GLOBAL_NPMRC="${NVM_VERSION_DIR}/etc/npmrc"
2267+
if nvm_npmrc_bad_news_bears "${NVM_NPM_GLOBAL_NPMRC}"; then
2268+
if [ "_${NVM_DELETE_PREFIX}" = "_1" ]; then
2269+
npm config --global --loglevel=warn delete prefix
2270+
npm config --global --loglevel=warn delete globalconfig
2271+
else
2272+
nvm_err "Your global npmrc file ($(nvm_sanitize_path "${NVM_NPM_GLOBAL_NPMRC}"))"
2273+
nvm_err 'has a `globalconfig` and/or a `prefix` setting, which are incompatible with nvm.'
2274+
nvm_err "Run \`${NVM_COMMAND}\` to unset it."
2275+
return 10
2276+
fi
2277+
fi
2278+
2279+
local NVM_NPM_USER_NPMRC
2280+
NVM_NPM_USER_NPMRC="${HOME}/.npmrc"
2281+
if nvm_npmrc_bad_news_bears "${NVM_NPM_USER_NPMRC}"; then
2282+
if [ "_${NVM_DELETE_PREFIX}" = "_1" ]; then
2283+
npm config --loglevel=warn delete prefix --userconfig="${NVM_NPM_USER_NPMRC}"
2284+
npm config --loglevel=warn delete globalconfig --userconfig="${NVM_NPM_USER_NPMRC}"
2285+
else
2286+
nvm_err "Your user’s .npmrc file ($(nvm_sanitize_path "${NVM_NPM_USER_NPMRC}"))"
2287+
nvm_err 'has a `globalconfig` and/or a `prefix` setting, which are incompatible with nvm.'
2288+
nvm_err "Run \`${NVM_COMMAND}\` to unset it."
2289+
return 10
2290+
fi
2291+
fi
2292+
2293+
local NVM_NPM_PROJECT_NPMRC
2294+
NVM_NPM_PROJECT_NPMRC="$(nvm_find_project_dir)/.npmrc"
2295+
if nvm_npmrc_bad_news_bears "${NVM_NPM_PROJECT_NPMRC}"; then
22392296
if [ "_${NVM_DELETE_PREFIX}" = "_1" ]; then
22402297
npm config --loglevel=warn delete prefix
2298+
npm config --loglevel=warn delete globalconfig
22412299
else
2242-
nvm deactivate >/dev/null 2>&1
2243-
nvm_err "nvm is not compatible with the npm config \"prefix\" option: currently set to \"${NVM_NPM_PREFIX}\""
2244-
if nvm_has 'npm'; then
2245-
nvm_err "Run \`npm config delete prefix\` or \`${NVM_COMMAND}\` to unset it."
2246-
else
2247-
nvm_err "Run \`${NVM_COMMAND}\` to unset it."
2248-
fi
2249-
if [ "${NVM_OS}" = 'darwin' ]; then
2250-
nvm_err "Make sure your username ($(whoami)) matches the one in your \$HOME path."
2251-
nvm_err "See the \"macOS Troubleshooting\" section in the docs for more information."
2252-
fi
2300+
nvm_err "Your project npmrc file ($(nvm_sanitize_path "${NVM_NPM_PROJECT_NPMRC}"))"
2301+
nvm_err 'has a `globalconfig` and/or a `prefix` setting, which are incompatible with nvm.'
2302+
nvm_err "Run \`${NVM_COMMAND}\` to unset it."
22532303
return 10
22542304
fi
22552305
fi
@@ -3703,6 +3753,7 @@ nvm() {
37033753
nvm_sanitize_path nvm_has_colors nvm_process_parameters \
37043754
nvm_node_version_has_solaris_binary nvm_iojs_version_has_solaris_binary \
37053755
nvm_curl_libz_support nvm_command_info nvm_is_zsh nvm_stdout_is_terminal \
3756+
nvm_npmrc_bad_news_bears \
37063757
>/dev/null 2>&1
37073758
unset NVM_RC_VERSION NVM_NODEJS_ORG_MIRROR NVM_IOJS_ORG_MIRROR NVM_DIR \
37083759
NVM_CD_FLAGS NVM_BIN NVM_INC NVM_MAKE_JOBS \

test/fast/Unit tests/nvm_die_on_prefix

Lines changed: 105 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
TEST_PWD=$(pwd)
44
TEST_DIR="$TEST_PWD/nvm_die_on_prefix_tmp"
55

6+
\. ../../../nvm.sh
7+
8+
TEST_VERSION_DIR="${TEST_DIR}/version"
9+
610
cleanup () {
711
rm -rf "$TEST_DIR"
812
alias nvm_has='\nvm_has'
@@ -18,8 +22,6 @@ die () {
1822

1923
[ ! -e "$TEST_DIR" ] && mkdir "$TEST_DIR"
2024

21-
\. ../../../nvm.sh
22-
2325
OUTPUT="$(nvm_die_on_prefix 2>&1)"
2426
EXPECTED_OUTPUT="First argument \"delete the prefix\" must be zero or one"
2527
EXIT_CODE="$(nvm_die_on_prefix >/dev/null 2>&1; echo $?)"
@@ -44,14 +46,6 @@ OUTPUT="$(nvm_die_on_prefix 0 version_dir foo 2>&1)"
4446

4547
nvm_has() { return 0; }
4648

47-
npm() {
48-
local args
49-
args="$@"
50-
if [ "_$args" = "_config --loglevel=warn get prefix" ]; then
51-
echo "$(nvm_version_dir new)/good prefix"
52-
fi
53-
}
54-
5549
OUTPUT="$(nvm_die_on_prefix 0 foo "$(nvm_version_dir new)" 2>&1)"
5650
[ -z "$OUTPUT" ] || die "'nvm_die_on_prefix' was not a noop when prefix is good; got '$OUTPUT'"
5751

@@ -90,18 +84,106 @@ EXIT_CODE="$(export npm_CONFIG_PREFIX=bar ; nvm_die_on_prefix 0 foo "$(nvm_versi
9084
[ "_$OUTPUT" = "_$EXPECTED_OUTPUT" ] || die "'npm_CONFIG_PREFIX=bar nvm_die_on_prefix 0 foo' did not error with '$EXPECTED_OUTPUT'; got '$OUTPUT'"
9185
[ "_$EXIT_CODE" = "_4" ] || die "'npm_CONFIG_PREFIX=bar nvm_die_on_prefix 0 foo' did not exit with 4; got '$EXIT_CODE'"
9286

93-
npm() {
94-
local args
95-
args="$@"
96-
if [ "_$args" = "_config --loglevel=warn get prefix" ]; then
97-
echo "./bad prefix"
98-
fi
99-
}
100-
OUTPUT="$(nvm_die_on_prefix 0 foo "$(nvm_version_dir new)" 2>&1)"
101-
EXPECTED_OUTPUT="nvm is not compatible with the npm config \"prefix\" option: currently set to \"./bad prefix\"
102-
Run \`npm config delete prefix\` or \`foo\` to unset it."
103-
EXIT_CODE="$(nvm_die_on_prefix 0 foo "$(nvm_version_dir new)" >/dev/null 2>&1; echo $?)"
104-
[ "_$OUTPUT" = "_$EXPECTED_OUTPUT" ] || die "'nvm_die_on_prefix 0 foo' did not error with '$EXPECTED_OUTPUT' with bad prefix set; got '$OUTPUT'"
105-
[ "_$EXIT_CODE" = "_10" ] || die "'nvm_die_on_prefix 0 foo' did not exit with 10 with bad prefix set; got '$EXIT_CODE'"
87+
# npmrc tests
88+
(
89+
cd "${TEST_DIR}"
90+
touch package.json
91+
92+
# project: prefix
93+
echo 'prefix=garbage' > .npmrc
94+
OUTPUT="$(nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}" 2>&1)"
95+
EXPECTED_OUTPUT="Your project npmrc file ($(nvm_sanitize_path "${TEST_DIR}")/.npmrc)
96+
has a \`globalconfig\` and/or a \`prefix\` setting, which are incompatible with nvm.
97+
Run \`foo\` to unset it."
98+
EXIT_CODE="$(nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}" >/dev/null 2>&1; echo $?)"
99+
[ "_$OUTPUT" = "_$EXPECTED_OUTPUT" ] || die "'nvm_die_on_prefix 0 foo' with project .npmrc that has prefix did not error with '$EXPECTED_OUTPUT'; got '$OUTPUT'"
100+
[ "_$EXIT_CODE" = "_10" ] || die "'nvm_die_on_prefix 0 foo' with project .npmrc that has prefix did not exit with 10; got '$EXIT_CODE'"
101+
102+
# project: globalconfig
103+
echo 'globalconfig=garbage' > .npmrc
104+
OUTPUT="$(nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}" 2>&1)"
105+
EXPECTED_OUTPUT="Your project npmrc file ($(nvm_sanitize_path "${TEST_DIR}")/.npmrc)
106+
has a \`globalconfig\` and/or a \`prefix\` setting, which are incompatible with nvm.
107+
Run \`foo\` to unset it."
108+
EXIT_CODE="$(nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}" >/dev/null 2>&1; echo $?)"
109+
[ "_$OUTPUT" = "_$EXPECTED_OUTPUT" ] || die "'nvm_die_on_prefix 0 foo' with project .npmrc that has globalconfig did not error with '$EXPECTED_OUTPUT'; got '$OUTPUT'"
110+
[ "_$EXIT_CODE" = "_10" ] || die "'nvm_die_on_prefix 0 foo' with project .npmrc that has globalconfig did not exit with 10; got '$EXIT_CODE'"
111+
112+
rm "${TEST_DIR}/.npmrc" || die '.npmrc could not be removed'
113+
114+
mkdir -p "${TEST_VERSION_DIR}"
115+
GLOBAL_NPMRC="${TEST_VERSION_DIR}/etc/npmrc"
116+
mkdir -p "${TEST_VERSION_DIR}/etc"
117+
118+
BUILTIN_NPMRC="${TEST_VERSION_DIR}/lib/node_modules/npm/npmrc"
119+
mkdir -p "${TEST_VERSION_DIR}/lib/node_modules/npm/"
120+
121+
export HOME="${TEST_VERSION_DIR}"
122+
USER_NPMRC="${TEST_VERSION_DIR}/.npmrc"
123+
124+
# global: prefix
125+
echo 'prefix=garbage' > "${GLOBAL_NPMRC}"
126+
OUTPUT="$(nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}" 2>&1)"
127+
EXPECTED_OUTPUT="Your global npmrc file ($(nvm_sanitize_path "${GLOBAL_NPMRC}"))
128+
has a \`globalconfig\` and/or a \`prefix\` setting, which are incompatible with nvm.
129+
Run \`foo\` to unset it."
130+
EXIT_CODE="$(nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}" >/dev/null 2>&1; echo $?)"
131+
[ "_$OUTPUT" = "_$EXPECTED_OUTPUT" ] || die "'nvm_die_on_prefix 0 foo' with global npmrc that has prefix did not error with '$EXPECTED_OUTPUT'; got '$OUTPUT'"
132+
[ "_$EXIT_CODE" = "_10" ] || die "'nvm_die_on_prefix 0 foo' with global npmrc that has prefix did not exit with 10; got '$EXIT_CODE'"
133+
134+
# global: globalconfig
135+
echo 'globalconfig=garbage' > "${GLOBAL_NPMRC}"
136+
OUTPUT="$(nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}" 2>&1)"
137+
EXPECTED_OUTPUT="Your global npmrc file ($(nvm_sanitize_path "${GLOBAL_NPMRC}"))
138+
has a \`globalconfig\` and/or a \`prefix\` setting, which are incompatible with nvm.
139+
Run \`foo\` to unset it."
140+
EXIT_CODE="$(nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}" >/dev/null 2>&1; echo $?)"
141+
[ "_$OUTPUT" = "_$EXPECTED_OUTPUT" ] || die "'nvm_die_on_prefix 0 foo' with global npmrc that has globalconfig did not error with '$EXPECTED_OUTPUT'; got '$OUTPUT'"
142+
[ "_$EXIT_CODE" = "_10" ] || die "'nvm_die_on_prefix 0 foo' with global npmrc that has globalconfig did not exit with 10; got '$EXIT_CODE'"
143+
144+
rm "${GLOBAL_NPMRC}" || die "${GLOBAL_NPMRC} could not be removed"
145+
146+
# builtin: prefix
147+
echo 'prefix=garbage' > "${BUILTIN_NPMRC}"
148+
OUTPUT="$(nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}" 2>&1)"
149+
EXPECTED_OUTPUT="Your builtin npmrc file ($(nvm_sanitize_path "${BUILTIN_NPMRC}"))
150+
has a \`globalconfig\` and/or a \`prefix\` setting, which are incompatible with nvm.
151+
Run \`foo\` to unset it."
152+
EXIT_CODE="$(nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}" >/dev/null 2>&1; echo $?)"
153+
[ "_$OUTPUT" = "_$EXPECTED_OUTPUT" ] || die "'nvm_die_on_prefix 0 foo' with builtin npmrc that has prefix did not error with '$EXPECTED_OUTPUT'; got '$OUTPUT'"
154+
[ "_$EXIT_CODE" = "_10" ] || die "'nvm_die_on_prefix 0 foo' with builtin npmrc that has prefix did not exit with 10; got '$EXIT_CODE'"
155+
156+
# builtin: globalconfig
157+
echo 'globalconfig=garbage' > "${BUILTIN_NPMRC}"
158+
OUTPUT="$(nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}" 2>&1)"
159+
EXPECTED_OUTPUT="Your builtin npmrc file ($(nvm_sanitize_path "${BUILTIN_NPMRC}"))
160+
has a \`globalconfig\` and/or a \`prefix\` setting, which are incompatible with nvm.
161+
Run \`foo\` to unset it."
162+
EXIT_CODE="$(nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}" >/dev/null 2>&1; echo $?)"
163+
[ "_$OUTPUT" = "_$EXPECTED_OUTPUT" ] || die "'nvm_die_on_prefix 0 foo' with builtin npmrc that has globalconfig did not error with '$EXPECTED_OUTPUT'; got '$OUTPUT'"
164+
[ "_$EXIT_CODE" = "_10" ] || die "'nvm_die_on_prefix 0 foo' with builtin npmrc that has globalconfig did not exit with 10; got '$EXIT_CODE'"
165+
166+
rm "${BUILTIN_NPMRC}" || die "${BUILTIN_NPMRC} could not be removed"
167+
168+
# user: prefix
169+
echo 'prefix=garbage' > "${USER_NPMRC}"
170+
OUTPUT="$(nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}" 2>&1)"
171+
EXPECTED_OUTPUT="Your user’s .npmrc file ($(nvm_sanitize_path "${USER_NPMRC}"))
172+
has a \`globalconfig\` and/or a \`prefix\` setting, which are incompatible with nvm.
173+
Run \`foo\` to unset it."
174+
EXIT_CODE="$(nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}" >/dev/null 2>&1; echo $?)"
175+
[ "_$OUTPUT" = "_$EXPECTED_OUTPUT" ] || die "'nvm_die_on_prefix 0 foo' with user .npmrc that has prefix did not error with '$EXPECTED_OUTPUT'; got '$OUTPUT'"
176+
[ "_$EXIT_CODE" = "_10" ] || die "'nvm_die_on_prefix 0 foo' with user .npmrc that has prefix did not exit with 10; got '$EXIT_CODE'"
177+
178+
# user: globalconfig
179+
echo 'globalconfig=garbage' > "${USER_NPMRC}"
180+
OUTPUT="$(nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}" 2>&1)"
181+
EXPECTED_OUTPUT="Your user’s .npmrc file ($(nvm_sanitize_path "${USER_NPMRC}"))
182+
has a \`globalconfig\` and/or a \`prefix\` setting, which are incompatible with nvm.
183+
Run \`foo\` to unset it."
184+
EXIT_CODE="$(nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}" >/dev/null 2>&1; echo $?)"
185+
[ "_$OUTPUT" = "_$EXPECTED_OUTPUT" ] || die "'nvm_die_on_prefix 0 foo' with user .npmrc that has globalconfig did not error with '$EXPECTED_OUTPUT'; got '$OUTPUT'"
186+
[ "_$EXIT_CODE" = "_10" ] || die "'nvm_die_on_prefix 0 foo' with user .npmrc that has globalconfig did not exit with 10; got '$EXIT_CODE'"
187+
)
106188

107189
cleanup

0 commit comments

Comments
 (0)