commit:     450ca5aac89525d612b00824380e61dca33177a0
Author:     Kerin Millar <kfm <AT> plushkava <DOT> net>
AuthorDate: Tue Jul  1 19:04:26 2025 +0000
Commit:     Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Fri Jul  4 02:17:01 2025 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=450ca5aa

misc-functions.sh: avoid repeatedly testing readlink -f in canonicalize()

Presently, there are two implementations of canonicalize(), one of which
serves to cover situations where the readlink(1) utility is either
unavailable or does not support the -f option. Upon first being called,
a test is performed to determine which should be used, with the result
being cached by the 'READLINK_F_WORKS' variable. The intent is to avoid
repeating this test on subsequent occasions that the function is called.

However, owing to the way in which the function is used, the variable
confers no benefit. Consider the following demonstration, which shows
that the variable will be declared after the point at which bash has
forked to create a subshell.

$ target=$(canonicalize /bin; declare -p READLINK_F_WORKS >&2)
declare -- READLINK_F_WORKS="true"
$ declare -p READLINK_F_WORKS
-bash: declare: READLINK_F_WORKS: not found

Address this issue by having the "misc-functions.sh" unit gauge the
availability and capability of readlink(1) at the the time that is
sourced, declaring the appropriate form of the function in advance of
its invocation. This should particularly benefit the "05prefix" QA test.

Fixes: ca46b021359ffa13a808f99dd635a6958b369be5
Signed-off-by: Kerin Millar <kfm <AT> plushkava.net>
Signed-off-by: Sam James <sam <AT> gentoo.org>

 bin/misc-functions.sh | 55 ++++++++++++++++++++++-----------------------------
 1 file changed, 24 insertions(+), 31 deletions(-)

diff --git a/bin/misc-functions.sh b/bin/misc-functions.sh
index d414e11f8f..abddef9f18 100755
--- a/bin/misc-functions.sh
+++ b/bin/misc-functions.sh
@@ -47,39 +47,32 @@ install_symlink_html_docs() {
        fi
 }
 
-# replacement for "readlink -f" or "realpath"
-READLINK_F_WORKS=""
-canonicalize() {
-       if [[ -z ${READLINK_F_WORKS} ]] ; then
-               if [[ $(readlink -f -- /../ 2>/dev/null) == "/" ]] ; then
-                       READLINK_F_WORKS=true
-               else
-                       READLINK_F_WORKS=false
-               fi
-       fi
-       if ${READLINK_F_WORKS} ; then
+if [[ $(readlink -f /../ 2>/dev/null) == / ]]; then
+       canonicalize() {
                readlink -f -- "$@"
-               return
-       fi
-
-       local f=$1 b n=10 wd=$(pwd)
-       while (( n-- > 0 )); do
-               while [[ ${f: -1} = / && ${#f} -gt 1 ]]; do
-                       f=${f%/}
+       }
+else
+       # replacement for "readlink -f" or "realpath"
+       canonicalize() {
+               local f=$1 b n=10 wd=$(pwd)
+               while (( n-- > 0 )); do
+                       while [[ ${f: -1} = / && ${#f} -gt 1 ]]; do
+                               f=${f%/}
+                       done
+                       b=${f##*/}
+                       cd "${f%"${b}"}" 2>/dev/null || break
+                       if [[ ! -L ${b} ]]; then
+                               f=$(pwd -P)
+                               echo "${f%/}/${b}"
+                               cd "${wd}"
+                               return 0
+                       fi
+                       f=$(readlink "${b}")
                done
-               b=${f##*/}
-               cd "${f%"${b}"}" 2>/dev/null || break
-               if [[ ! -L ${b} ]]; then
-                       f=$(pwd -P)
-                       echo "${f%/}/${b}"
-                       cd "${wd}"
-                       return 0
-               fi
-               f=$(readlink "${b}")
-       done
-       cd "${wd}"
-       return 1
-}
+               cd "${wd}"
+               return 1
+       }
+fi
 
 install_qa_check() {
        local d f i qa_var x paths qa_checks=() checks_run=()

Reply via email to