mirror of
https://github.com/pyenv/pyenv.git
synced 2026-04-06 13:45:11 +09:00
rehash: streamline executables discovery; fix regression (#3418)
Separate the corner-cutting code for `rehash' into a dedicated branch. Saves some more time (about 100ms for the large fixture)
This commit is contained in:
parent
d5fa1e225e
commit
8037f22665
@ -110,17 +110,6 @@ remove_outdated_shims() {
|
||||
done
|
||||
}
|
||||
|
||||
# List basenames of executables for every Python version
|
||||
list_executable_names() {
|
||||
local version file
|
||||
pyenv-versions --bare --skip-aliases | \
|
||||
while read -r version; do
|
||||
for file in "${PYENV_ROOT}/versions/${version}/bin/"*; do
|
||||
echo "${file##*/}"
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
# The basename of each argument passed to `make_shims` will be
|
||||
# registered for installation as a shim. In this way, plugins may call
|
||||
# `make_shims` with a glob to register many shims at once.
|
||||
@ -196,7 +185,7 @@ shopt -s nullglob
|
||||
create_prototype_shim
|
||||
remove_outdated_shims
|
||||
# shellcheck disable=SC2046
|
||||
make_shims $(list_executable_names)
|
||||
make_shims $(pyenv-versions --executables)
|
||||
|
||||
|
||||
# Allow plugins to register shims.
|
||||
|
||||
@ -1,13 +1,21 @@
|
||||
#!/usr/bin/env bash
|
||||
# Summary: List all Python versions available to pyenv
|
||||
# Usage: pyenv versions [--bare] [--skip-aliases] [--skip-envs]
|
||||
# Usage: pyenv versions [--bare] [--skip-aliases] [--skip-envs] [--executables]
|
||||
#
|
||||
# Lists all Python versions found in `$PYENV_ROOT/versions/*'.
|
||||
#
|
||||
# --bare List just the names, omit `system'
|
||||
# --skip-aliases Skip symlinks to other versions and to virtual environments
|
||||
# --skip-envs Skip virtual environments (under <version>/envs)
|
||||
# --executables Internal. Overrides other options.
|
||||
# Optimally get a deduplicated list of all executable names in Pyenv-managed
|
||||
# versions and environments for `pyenv rehash'
|
||||
#
|
||||
|
||||
set -e
|
||||
[ -n "$PYENV_DEBUG" ] && set -x
|
||||
|
||||
unset bare skip_aliases skip_envs
|
||||
unset bare skip_aliases skip_envs executables
|
||||
# Provide pyenv completions
|
||||
for arg; do
|
||||
case "$arg" in
|
||||
@ -16,6 +24,7 @@ for arg; do
|
||||
echo --skip-aliases
|
||||
echo --skip-envs
|
||||
exit ;;
|
||||
--executables ) executables=1; break ;;
|
||||
--bare ) bare=1 ;;
|
||||
--skip-aliases ) skip_aliases=1 ;;
|
||||
--skip-envs ) skip_envs=1 ;;
|
||||
@ -26,31 +35,21 @@ for arg; do
|
||||
esac
|
||||
done
|
||||
|
||||
# Fast path for --bare --skip-aliases: skip sort and full realpath resolution
|
||||
if [[ -n "$bare" && -n "$skip_aliases" ]]; then
|
||||
|
||||
versions_dir="${PYENV_ROOT}/versions"
|
||||
|
||||
# Fast path for rehash: skip filtering and link resolution
|
||||
if [[ -n "$executables" ]]; then
|
||||
if [ -d "$versions_dir" ]; then
|
||||
shopt -s dotglob nullglob
|
||||
for path in "$versions_dir"/*/; do
|
||||
path="${path%/}"
|
||||
if [ -L "$path" ]; then
|
||||
# Relative link = internal alias → skip; absolute = external → keep
|
||||
[[ "$(readlink "$path")" == /* ]] || continue
|
||||
fi
|
||||
echo "${path##*/}"
|
||||
if [[ -z "$skip_envs" ]]; then
|
||||
for env_path in "${path}/envs/"*; do
|
||||
[ -d "$env_path" ] && echo "${env_path#${versions_dir}/}"
|
||||
done
|
||||
fi
|
||||
done
|
||||
# MacOS 12+ and FreeBSD 15 support `xargs -r -0' and `basename -a'
|
||||
# `sort -u` is simpler and a bit faster than `awk '!seen[$0]++'`, with the same result for rehash purposes
|
||||
printf '%s\0' "$versions_dir"/*/bin/* "$versions_dir"/*/envs/*/bin/* | xargs -0 -r basename -a | sort -u
|
||||
shopt -u dotglob nullglob
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
versions_dir="${PYENV_ROOT}/versions"
|
||||
|
||||
if ! enable -f "${BASH_SOURCE%/*}"/pyenv-realpath.dylib realpath 2>/dev/null; then
|
||||
if [ -n "$PYENV_NATIVE_EXT" ]; then
|
||||
echo "pyenv: failed to load \`realpath' builtin" >&2
|
||||
|
||||
@ -135,7 +135,7 @@ path_without() {
|
||||
if [ "$found" != "${PYENV_ROOT}/shims" ]; then
|
||||
alt="${PYENV_TEST_DIR}/$(echo "${found#/}" | tr '/' '-')"
|
||||
mkdir -p "$alt"
|
||||
for util in bash head cut readlink greadlink tr sed; do
|
||||
for util in bash head cut readlink greadlink tr sed xargs basename sort; do
|
||||
if [ -x "${found}/$util" ]; then
|
||||
ln -s "${found}/$util" "${alt}/$util"
|
||||
fi
|
||||
|
||||
@ -11,6 +11,11 @@ create_alias() {
|
||||
ln -s "$2" "${PYENV_ROOT}/versions/$1"
|
||||
}
|
||||
|
||||
create_external_version() {
|
||||
mkdir -p "$PYENV_TEST_DIR/${1:?}"
|
||||
create_alias "${1:?}" "$PYENV_TEST_DIR/${1:?}"
|
||||
}
|
||||
|
||||
_setup() {
|
||||
mkdir -p "$PYENV_TEST_DIR"
|
||||
cd "$PYENV_TEST_DIR"
|
||||
@ -168,15 +173,39 @@ OUT
|
||||
@test "doesn't list symlink aliases when --skip-aliases" {
|
||||
create_version "1.8.7"
|
||||
create_alias "1.8" "1.8.7"
|
||||
mkdir moo
|
||||
create_alias "1.9" "${PWD}/moo"
|
||||
create_external_version "moo"
|
||||
|
||||
run pyenv-versions --bare --skip-aliases
|
||||
assert_success
|
||||
|
||||
assert_output <<OUT
|
||||
1.8.7
|
||||
1.9
|
||||
moo
|
||||
OUT
|
||||
}
|
||||
|
||||
@test "--executables lists executables everywhere and overrides other switches" {
|
||||
create_alt_executable_in_version "3.5.0" "python"
|
||||
create_alt_executable_in_version "3.5.0" "python1"
|
||||
create_alt_executable_in_version "3.6.0" "python"
|
||||
create_alt_executable_in_version "3.5.0/envs/foo" "python_foo"
|
||||
create_alt_executable_in_version "3.6.0/envs/bar" "python_bar"
|
||||
create_alias "bar" "3.6.0/envs/bar"
|
||||
create_external_version "moo"
|
||||
create_alt_executable_in_version "moo" "moopython"
|
||||
|
||||
run pyenv-versions --skip-aliases --skip-envs --executables
|
||||
assert_success
|
||||
#The sort order does not matter for this functionality. However,
|
||||
#MacOS 15 `sort` sorts differently that Linux's due to a different LC_COLLATE definition for en-US:
|
||||
#https://unix.stackexchange.com/questions/362728/why-does-gnu-sort-sort-differently-on-my-osx-machine-and-linux-machine
|
||||
#So to get a match, we have to check against the same order that the local `sort` produces
|
||||
sort <<OUT | assert_output
|
||||
moopython
|
||||
python
|
||||
python1
|
||||
python_bar
|
||||
python_foo
|
||||
OUT
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user