mirror of
https://github.com/nvm-sh/nvm.git
synced 2026-10-23 06:44:48 +08:00
[Perf] Optimize nvm_tree_contains_path with in-memory POSIX parent-walk
Replace looping subshell process forks (dirname) in nvm_tree_contains_path with case-guarded in-memory POSIX parameter expansion () and exact string equality comparisons. Ensures literal string matching for glob metacharacters (*, ?, []) and full zsh compatibility across all platforms.
This commit is contained in:
committed by
Jordan Harband
parent
e361b93e4b
commit
cd84623ab2
41
nvm.sh
41
nvm.sh
@@ -547,6 +547,9 @@ else
|
||||
fi
|
||||
unset NVM_SCRIPT_SOURCE 2>/dev/null
|
||||
|
||||
# Performs pure in-memory POSIX path containment checking without subshell process forks.
|
||||
# Uses case-guarded ${pathdir%/*} for parent-walk and exact string equality (=) to ensure literal matching
|
||||
# for directory names containing glob metacharacters (*, ?, []) across all shells including zsh.
|
||||
nvm_tree_contains_path() {
|
||||
local tree
|
||||
tree="${1-}"
|
||||
@@ -558,16 +561,36 @@ nvm_tree_contains_path() {
|
||||
return 2
|
||||
fi
|
||||
|
||||
local previous_pathdir
|
||||
previous_pathdir="${node_path}"
|
||||
local pathdir
|
||||
pathdir=$(dirname "${previous_pathdir}")
|
||||
while [ "${pathdir}" != '' ] && [ "${pathdir}" != '.' ] && [ "${pathdir}" != '/' ] &&
|
||||
[ "${pathdir}" != "${tree}" ] && [ "${pathdir}" != "${previous_pathdir}" ]; do
|
||||
previous_pathdir="${pathdir}"
|
||||
pathdir=$(dirname "${previous_pathdir}")
|
||||
local clean_tree
|
||||
clean_tree="${tree}"
|
||||
|
||||
# Strip trailing slashes in shell memory (e.g., "dir//" -> "dir")
|
||||
while [ "${clean_tree}" != "${clean_tree%/}" ]; do
|
||||
clean_tree="${clean_tree%/}"
|
||||
done
|
||||
[ "${pathdir}" = "${tree}" ]
|
||||
if [ -z "${clean_tree}" ]; then
|
||||
clean_tree='/'
|
||||
fi
|
||||
|
||||
# Pure in-memory POSIX parent-walk using parameter expansion instead of subshell dirname forks.
|
||||
# Uses literal string equality [ "${pathdir}" = "${clean_tree}" ] to prevent glob expansion bugs.
|
||||
local pathdir
|
||||
pathdir="${node_path}"
|
||||
while [ "${pathdir}" != '' ] && [ "${pathdir}" != '.' ] && [ "${pathdir}" != '/' ] &&
|
||||
[ "${pathdir}" != "${clean_tree}" ]; do
|
||||
case "${pathdir}" in
|
||||
*/*)
|
||||
pathdir="${pathdir%/*}"
|
||||
if [ -z "${pathdir}" ]; then
|
||||
pathdir='/'
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
[ "${pathdir}" = "${clean_tree}" ]
|
||||
}
|
||||
|
||||
nvm_find_project_dir() {
|
||||
|
||||
@@ -29,4 +29,11 @@ nvm_tree_contains_path tmp2 tmp2/node || die '"tmp2" should contain "tmp2/node"'
|
||||
|
||||
nvm_tree_contains_path tmp2 tmp/node && die '"tmp2" should not contain "tmp/node"'
|
||||
|
||||
nvm_tree_contains_path tmp/ tmp/node || die '"tmp/" should contain "tmp/node"'
|
||||
nvm_tree_contains_path tmp// tmp/node || die '"tmp//" should contain "tmp/node"'
|
||||
nvm_tree_contains_path / /tmp/node || die '"/" should contain "/tmp/node"'
|
||||
|
||||
nvm_tree_contains_path "tmp[glob]" "tmp[glob]/node" || die '"tmp[glob]" should contain "tmp[glob]/node"'
|
||||
nvm_tree_contains_path "tmp" "tmp[glob]/node" && die '"tmp" should not contain "tmp[glob]/node"'
|
||||
|
||||
cleanup
|
||||
|
||||
Reference in New Issue
Block a user