Skip to content

Commit aa6c9b9

Browse files
authored
init: don't silence automatic rehash; rehash: report final error but not provisional ones (pyenv#3377)
1 parent a944da7 commit aa6c9b9

4 files changed

Lines changed: 27 additions & 17 deletions

File tree

libexec/pyenv-init

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,10 +287,10 @@ function print_rehash() {
287287
if [ -z "$no_rehash" ]; then
288288
case "$shell" in
289289
pwsh )
290-
echo '& pyenv rehash 2>/dev/null'
290+
echo '& pyenv rehash'
291291
;;
292292
* )
293-
echo 'command pyenv rehash 2>/dev/null'
293+
echo 'command pyenv rehash'
294294
;;
295295
esac
296296
fi

libexec/pyenv-rehash

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,20 @@ PROTOTYPE_SHIM_PATH="${SHIM_PATH}/.pyenv-shim"
1010
# Create the shims directory if it doesn't already exist.
1111
mkdir -p "$SHIM_PATH"
1212

13+
declare last_acquire_error
14+
1315
acquire_lock() {
1416
# Ensure only one instance of pyenv-rehash is running at a time by
1517
# setting the shell's `noclobber` option and attempting to write to
1618
# the prototype shim file. If the file already exists, print a warning
1719
# to stderr and exit with a non-zero status.
1820
local ret
1921
set -o noclobber
20-
echo > "$PROTOTYPE_SHIM_PATH" 2>| /dev/null || ret=1
22+
last_acquire_error="$( { ( echo -n > "$PROTOTYPE_SHIM_PATH"; ) 2>&1 1>&3 3>&1-; } 3>&1)" || ret=1
2123
set +o noclobber
2224
[ -z "${ret}" ]
2325
}
2426

25-
# If we were able to obtain a lock, register a trap to clean up the
26-
# prototype shim when the process exits.
27-
trap release_lock EXIT
28-
2927
remove_prototype_shim() {
3028
rm -f "$PROTOTYPE_SHIM_PATH"
3129
}
@@ -39,11 +37,17 @@ if [ ! -w "$SHIM_PATH" ]; then
3937
exit 1
4038
fi
4139

42-
unset acquired
43-
start=$SECONDS
44-
while (( SECONDS <= start + ${PYENV_REHASH_TIMEOUT:-60} )); do
45-
if acquire_lock 2>/dev/null; then
40+
declare acquired tested_for_other_write_errors
41+
declare start=$SECONDS
42+
PYENV_REHASH_TIMEOUT=${PYENV_REHASH_TIMEOUT:-60}
43+
while (( SECONDS <= start + PYENV_REHASH_TIMEOUT )); do
44+
if acquire_lock; then
4645
acquired=1
46+
47+
# If we were able to obtain a lock, register a trap to clean up the
48+
# prototype shim when the process exits.
49+
trap release_lock EXIT
50+
4751
break
4852
else
4953
#Landlock sandbox subsystem in the Linux kernel returns false information in access() as of 6.14.0,
@@ -53,7 +57,7 @@ while (( SECONDS <= start + ${PYENV_REHASH_TIMEOUT:-60} )); do
5357
# in a way that taxes the usual use case as little as possible.
5458
if [[ -z $tested_for_other_write_errors ]]; then
5559
( t="$(TMPDIR="$SHIM_PATH" mktemp)" && rm "$t" ) && tested_for_other_write_errors=1 ||
56-
{ echo "pyenv: cannot rehash: $SHIM_PATH isnt writable" >&2; break; }
60+
{ echo "pyenv: cannot rehash: $SHIM_PATH isn't writable" >&2; break; }
5761
fi
5862
# POSIX sleep(1) doesn't provide subsecond precision, but many others do
5963
sleep 0.1 2>/dev/null || sleep 1
@@ -62,7 +66,9 @@ done
6266

6367
if [ -z "${acquired}" ]; then
6468
if [[ -n $tested_for_other_write_errors ]]; then
65-
echo "pyenv: cannot rehash: $PROTOTYPE_SHIM_PATH exists" >&2
69+
echo "pyenv: cannot rehash: couldn't acquire lock"\
70+
"$PROTOTYPE_SHIM_PATH for $PYENV_REHASH_TIMEOUT seconds. Last error message:" >&2
71+
echo "$last_acquire_error" >&2
6672
fi
6773
exit 1
6874
fi

test/init.bats

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ load test_helper
1414
@test "auto rehash" {
1515
run pyenv-init -
1616
assert_success
17-
assert_line "command pyenv rehash 2>/dev/null"
17+
assert_line "command pyenv rehash"
1818
}
1919

2020
@test "auto rehash for --path" {
2121
run pyenv-init --path
2222
assert_success
23-
assert_line "command pyenv rehash 2>/dev/null"
23+
assert_line "command pyenv rehash"
2424
}
2525

2626
@test "setup shell completions" {

test/rehash.bats

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,12 @@ load test_helper
2121
export PYENV_REHASH_TIMEOUT=1
2222
mkdir -p "${PYENV_ROOT}/shims"
2323
touch "${PYENV_ROOT}/shims/.pyenv-shim"
24-
run pyenv-rehash
25-
assert_failure "pyenv: cannot rehash: ${PYENV_ROOT}/shims/.pyenv-shim exists"
24+
#avoid failure due to a localized error message
25+
LANG=C run pyenv-rehash
26+
assert_failure <<!
27+
pyenv: cannot rehash: couldn't acquire lock ${PYENV_ROOT}/shims/.pyenv-shim for 1 seconds. Last error message:
28+
*/pyenv-rehash: line *: ${PYENV_ROOT}/shims/.pyenv-shim: cannot overwrite existing file
29+
!
2630
}
2731

2832
@test "wait until lock acquisition" {

0 commit comments

Comments
 (0)