From 09fbed1d4f937b6db0bffec24bc67ad9ad08ed41 Mon Sep 17 00:00:00 2001 From: Christian Fredrik Johnsen Date: Mon, 23 Dec 2024 14:47:36 +0300 Subject: [PATCH 1/3] fix: pyenv-rehash | do NOT create conda_exclusion_list if conda is not installed. I was doing some debugging with PYENV_DEBUG=1 and noticed that a lot of work was being done in conda.bash, even though I had not installed any conda versions like `mambaforge`. The solution is pretty simple, put all the code inside an if-block. This aligns with what @varikin found in his pull request #3037 Additionally, I have refactored the code slightly for readability (created function `build_conda_exclusion_list`), and added comments which should make it easier to understand what's going on. This commit simplifies debugging and should reduce the execution time of ```bash eval "$(pyenv init -)" ``` slightly. --- pyenv.d/rehash/conda.bash | 100 ++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 42 deletions(-) diff --git a/pyenv.d/rehash/conda.bash b/pyenv.d/rehash/conda.bash index 884cd4f2..6f65d2b4 100644 --- a/pyenv.d/rehash/conda.bash +++ b/pyenv.d/rehash/conda.bash @@ -11,48 +11,64 @@ conda_exists() { [ -n "${condas}" ] } -shims=() -shopt -s nullglob -for shim in $(cat "${BASH_SOURCE%/*}/conda.d/"*".list" | sort | uniq | sed -e 's/#.*$//' | sed -e '/^[[:space:]]*$/d'); do - if [ -n "${shim##*/}" ]; then - shims[${#shims[*]}]="${shim})return 0;;" - fi -done -shopt -u nullglob -eval "conda_shim(){ case \"\${1##*/}\" in ${shims[@]} *)return 1;;esac;}" - -# override `make_shims` to avoid conflict between pyenv-virtualenv's `envs.bash` -# https://github.com/pyenv/pyenv-virtualenv/blob/v20160716/etc/pyenv.d/rehash/envs.bash -make_shims() { - local file shim - for file do - shim="${file##*/}" - if ! conda_shim "${shim}" 1>&2; then - register_shim "$shim" - fi - done -} - -deregister_conda_shims() { - # adapted for Bash 4.x's associative array (#1749) - if declare -p registered_shims 2> /dev/null | grep -Eq '^(declare|typeset) -A'; then - for shim in ${!registered_shims[*]}; do - if conda_shim "${shim}" 1>&2; then - unset registered_shims[${shim}] - fi - done - else - local shim - local shims=() - for shim in ${registered_shims}; do - if ! conda_shim "${shim}" 1>&2; then - shims[${#shims[*]}]="${shim}" - fi - done - registered_shims=" ${shims[@]} " - fi -} - if conda_exists; then + + # Reads the list of `blacklisted` conda binaries + # from `conda.d/default.list` and creates a function + # `conda_shim` to skip creating shims for those binaries. + build_conda_exclusion_list() { + shims=() + shopt -s nullglob + for shim in $(cat "${BASH_SOURCE%/*}/conda.d/"*".list" | sort -u | sed -e 's/#.*$//' | sed -e '/^[[:space:]]*$/d'); do + if [ -n "${shim##*/}" ]; then + shims[${#shims[*]}]="${shim})return 0;;" + fi + done + shopt -u nullglob + eval \ +"conda_shim() { + case \"\${1##*/}\" in + ${shims[@]} + *) return 1;; + esac +}" + } + + # override `make_shims` to avoid conflict between pyenv-virtualenv's `envs.bash` + # https://github.com/pyenv/pyenv-virtualenv/blob/v20160716/etc/pyenv.d/rehash/envs.bash + # The only difference between this `make_shims` and the `make_shims` defined + # in `libexec/pyenv-rehash` is that this one calls `conda_shim` to check + # if shim is blacklisted. If blacklisted -> skip creating shim. + make_shims() { + local file shim + for file do + shim="${file##*/}" + if ! conda_shim "${shim}" 1>&2; then + register_shim "$shim" + fi + done + } + + deregister_conda_shims() { + # adapted for Bash 4.x's associative array (#1749) + if declare -p registered_shims 2> /dev/null | grep -Eq '^(declare|typeset) -A'; then + for shim in ${!registered_shims[*]}; do + if conda_shim "${shim}" 1>&2; then + unset registered_shims[${shim}] + fi + done + else + local shim + local shims=() + for shim in ${registered_shims}; do + if ! conda_shim "${shim}" 1>&2; then + shims[${#shims[*]}]="${shim}" + fi + done + registered_shims=" ${shims[@]} " + fi + } + + build_conda_exclusion_list deregister_conda_shims fi From ab2a5ad0301309bab86575e13c38977650df7751 Mon Sep 17 00:00:00 2001 From: Christian Fredrik Johnsen Date: Wed, 25 Dec 2024 12:21:50 +0100 Subject: [PATCH 2/3] style: place `greadlink` in coreutils section Applies to the conda blacklist in `pyenv.d/rehash/conda.d/default.list` No practical difference, but it looks misplaced when it sits at the end of the file. --- pyenv.d/rehash/conda.d/default.list | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyenv.d/rehash/conda.d/default.list b/pyenv.d/rehash/conda.d/default.list index f70b953b..3c906b4e 100644 --- a/pyenv.d/rehash/conda.d/default.list +++ b/pyenv.d/rehash/conda.d/default.list @@ -117,6 +117,7 @@ factor false fmt fold +greadlink groups head hostid @@ -191,5 +192,4 @@ wc who whoami yes -# --- end exclusions from coreutils -greadlink \ No newline at end of file +# --- end exclusions from coreutils \ No newline at end of file From 8e5379ebe34b49b134ee7ab2165f419eb1f77050 Mon Sep 17 00:00:00 2001 From: Christian Fredrik Johnsen Date: Wed, 25 Dec 2024 12:37:34 +0100 Subject: [PATCH 3/3] perf: faster execution of build_conda_exclusion_list 1) Got rid of useless call to `cat`, much better to simply use sed with file as argument. 2) Got rid of `sort -u`. There is no need to sort the list. Additionally, the list `pyenv.d/rehash/conda.d/default.list` only has unique entries, and even if you have duplicate entries, the function will still work. --> No need for sort nor unique. 3) Further improvement is simple, save a cached cleaned-list-v1.0 in `conda.d` and simple read from that file instead of doing `sed`, which must be a more expensive operation than simply reading from file. --- pyenv.d/rehash/conda.bash | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pyenv.d/rehash/conda.bash b/pyenv.d/rehash/conda.bash index 6f65d2b4..ab17ca13 100644 --- a/pyenv.d/rehash/conda.bash +++ b/pyenv.d/rehash/conda.bash @@ -18,13 +18,11 @@ if conda_exists; then # `conda_shim` to skip creating shims for those binaries. build_conda_exclusion_list() { shims=() - shopt -s nullglob - for shim in $(cat "${BASH_SOURCE%/*}/conda.d/"*".list" | sort -u | sed -e 's/#.*$//' | sed -e '/^[[:space:]]*$/d'); do + for shim in $(sed 's/#.*$//; /^[[:space:]]*$/d' "${BASH_SOURCE%/*}/conda.d/default.list"); do if [ -n "${shim##*/}" ]; then shims[${#shims[*]}]="${shim})return 0;;" fi done - shopt -u nullglob eval \ "conda_shim() { case \"\${1##*/}\" in