From 980963d2f6fc2f65e591846c2ca7249fc7b08101 Mon Sep 17 00:00:00 2001 From: Ned Deily Date: Wed, 6 Aug 2025 03:13:52 -0400 Subject: [PATCH 1/6] Create separate update_shell_profile.command from postflight.patch-profile --- Mac/BuildScript/build-installer.py | 2 +- .../resources/update_shell_profile.command | 116 ++++++++++++++++++ .../scripts/postflight.patch-profile | 6 +- 3 files changed, 120 insertions(+), 4 deletions(-) create mode 100755 Mac/BuildScript/resources/update_shell_profile.command diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 8ae2cff93d20826..4da6d9248488893 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -1747,7 +1747,7 @@ def main(): fn = os.path.join(folder, "ReadMe.rtf") patchFile("resources/ReadMe.rtf", fn) fn = os.path.join(folder, "Update Shell Profile.command") - patchScript("scripts/postflight.patch-profile", fn) + patchScript("resources/update_shell_profile.command", fn) fn = os.path.join(folder, "Install Certificates.command") patchScript("resources/install_certificates.command", fn) os.chmod(folder, STAT_0o755) diff --git a/Mac/BuildScript/resources/update_shell_profile.command b/Mac/BuildScript/resources/update_shell_profile.command new file mode 100755 index 000000000000000..3cf4d74de9f09a5 --- /dev/null +++ b/Mac/BuildScript/resources/update_shell_profile.command @@ -0,0 +1,116 @@ +#!/bin/sh + +echo "This script will update your shell profile when the 'bin' directory" +echo "of python is not early enough of the PATH of your shell." +echo "These changes will be effective only in shell windows that you open" +echo "after running this script." + +PYVER=@PYVER@ +PYTHON_ROOT="/Library/Frameworks/Python.framework/Versions/@PYVER@" + +if [ `id -ur` = 0 ]; then + # Run from the installer, do some trickery to fetch the information + # we need. + theShell="`finger $USER | grep Shell: | head -1 | awk '{ print $NF }'`" + +else + theShell="${SHELL}" +fi + +# Make sure the directory ${PYTHON_ROOT}/bin is on the users PATH. +BSH="`basename "${theShell}"`" +case "${BSH}" in +bash|ksh|sh|*csh|zsh|fish) + if [ `id -ur` = 0 ]; then + P=`su - ${USER} -c 'echo A-X-4-X@@$PATH@@X-4-X-A' | grep 'A-X-4-X@@.*@@X-4-X-A' | sed -e 's/^A-X-4-X@@//g' -e 's/@@X-4-X-A$//g'` + else + P="`(exec -l ${theShell} -c 'echo $PATH')`" + fi + ;; +*) + echo "Sorry, I don't know how to patch $BSH shells" + exit 0 + ;; +esac + +# Now ensure that our bin directory is on $P and before /usr/bin at that +for elem in `echo $P | tr ':' ' '` +do + if [ "${elem}" = "${PYTHON_ROOT}/bin" ]; then + echo "All right, you're a python lover already" + exit 0 + elif [ "${elem}" = "/usr/bin" ]; then + break + fi +done + +echo "${PYTHON_ROOT}/bin is not on your PATH or at least not early enough" +case "${BSH}" in +*csh) + if [ -f "${HOME}/.tcshrc" ]; then + RC="${HOME}/.tcshrc" + else + RC="${HOME}/.cshrc" + fi + # Create backup copy before patching + if [ -f "${RC}" ]; then + cp -fp "${RC}" "${RC}.pysave" + fi + echo "" >> "${RC}" + echo "# Setting PATH for Python ${PYVER}" >> "${RC}" + echo "# The original version is saved in .cshrc.pysave" >> "${RC}" + echo "set path=(${PYTHON_ROOT}/bin "'$path'")" >> "${RC}" + if [ `id -ur` = 0 ]; then + chown -h "${USER}" "${RC}" + fi + exit 0 + ;; +bash) + if [ -e "${HOME}/.bash_profile" ]; then + PR="${HOME}/.bash_profile" + elif [ -e "${HOME}/.bash_login" ]; then + PR="${HOME}/.bash_login" + elif [ -e "${HOME}/.profile" ]; then + PR="${HOME}/.profile" + else + PR="${HOME}/.bash_profile" + fi + ;; +fish) + CONFIG_DIR="${HOME}/.config/fish/conf.d/" + RC="${CONFIG_DIR}/python-${PYVER}.fish" + mkdir -p "$CONFIG_DIR" + if [ -f "${RC}" ]; then + cp -fp "${RC}" "${RC}.pysave" + fi + echo "# Setting PATH for Python ${PYVER}" > "${RC}" + if [ -f "${RC}.pysave" ]; then + echo "# The original version is saved in ${RC}.pysave" >> "${RC}" + fi + echo "fish_add_path -g \"${PYTHON_ROOT}/bin\"" >> "${RC}" + if [ `id -ur` = 0 ]; then + chown -h "${USER}" "${RC}" + fi + exit 0 + ;; +zsh) + PR="${HOME}/.zprofile" + ;; +*sh) + PR="${HOME}/.profile" + ;; +esac + +# Create backup copy before patching +if [ -f "${PR}" ]; then + cp -fp "${PR}" "${PR}.pysave" +fi +echo "" >> "${PR}" +echo "# Setting PATH for Python ${PYVER}" >> "${PR}" +echo "# The original version is saved in `basename ${PR}`.pysave" >> "${PR}" +echo 'PATH="'"${PYTHON_ROOT}/bin"':${PATH}"' >> "${PR}" +echo 'export PATH' >> "${PR}" +if [ `id -ur` = 0 ]; then + chown -h "${USER}" "${PR}" +fi +exit 0 diff --git a/Mac/BuildScript/scripts/postflight.patch-profile b/Mac/BuildScript/scripts/postflight.patch-profile index 9caf62211ddd16c..3cf4d74de9f09a5 100755 --- a/Mac/BuildScript/scripts/postflight.patch-profile +++ b/Mac/BuildScript/scripts/postflight.patch-profile @@ -61,7 +61,7 @@ case "${BSH}" in echo "# The original version is saved in .cshrc.pysave" >> "${RC}" echo "set path=(${PYTHON_ROOT}/bin "'$path'")" >> "${RC}" if [ `id -ur` = 0 ]; then - chown "${USER}" "${RC}" + chown -h "${USER}" "${RC}" fi exit 0 ;; @@ -89,7 +89,7 @@ fish) fi echo "fish_add_path -g \"${PYTHON_ROOT}/bin\"" >> "${RC}" if [ `id -ur` = 0 ]; then - chown "${USER}" "${RC}" + chown -h "${USER}" "${RC}" fi exit 0 ;; @@ -111,6 +111,6 @@ echo "# The original version is saved in `basename ${PR}`.pysave" >> "${PR}" echo 'PATH="'"${PYTHON_ROOT}/bin"':${PATH}"' >> "${PR}" echo 'export PATH' >> "${PR}" if [ `id -ur` = 0 ]; then - chown "${USER}" "${PR}" + chown -h "${USER}" "${PR}" fi exit 0 From 1416dbbb9583a23f1212c6dad36134252f1964ea Mon Sep 17 00:00:00 2001 From: Ned Deily Date: Wed, 6 Aug 2025 04:33:51 -0400 Subject: [PATCH 2/6] postflight.patch-profile refactor --- .../scripts/postflight.patch-profile | 158 +++++++++--------- 1 file changed, 75 insertions(+), 83 deletions(-) diff --git a/Mac/BuildScript/scripts/postflight.patch-profile b/Mac/BuildScript/scripts/postflight.patch-profile index 3cf4d74de9f09a5..1cca8eb0252d988 100755 --- a/Mac/BuildScript/scripts/postflight.patch-profile +++ b/Mac/BuildScript/scripts/postflight.patch-profile @@ -1,116 +1,108 @@ #!/bin/sh -echo "This script will update your shell profile when the 'bin' directory" -echo "of python is not early enough of the PATH of your shell." -echo "These changes will be effective only in shell windows that you open" -echo "after running this script." - PYVER=@PYVER@ PYTHON_ROOT="/Library/Frameworks/Python.framework/Versions/@PYVER@" -if [ `id -ur` = 0 ]; then - # Run from the installer, do some trickery to fetch the information - # we need. - theShell="`finger $USER | grep Shell: | head -1 | awk '{ print $NF }'`" +set -e -else - theShell="${SHELL}" -fi +# Run from the installer, do some trickery to fetch the information +# we need. +theShell="`finger $USER | grep Shell: | head -1 | awk '{ print $NF }'`" # Make sure the directory ${PYTHON_ROOT}/bin is on the users PATH. BSH="`basename "${theShell}"`" case "${BSH}" in bash|ksh|sh|*csh|zsh|fish) - if [ `id -ur` = 0 ]; then - P=`su - ${USER} -c 'echo A-X-4-X@@$PATH@@X-4-X-A' | grep 'A-X-4-X@@.*@@X-4-X-A' | sed -e 's/^A-X-4-X@@//g' -e 's/@@X-4-X-A$//g'` - else - P="`(exec -l ${theShell} -c 'echo $PATH')`" - fi - ;; + true + ;; *) - echo "Sorry, I don't know how to patch $BSH shells" - exit 0 - ;; + exit 0 + ;; esac -# Now ensure that our bin directory is on $P and before /usr/bin at that -for elem in `echo $P | tr ':' ' '` -do - if [ "${elem}" = "${PYTHON_ROOT}/bin" ]; then - echo "All right, you're a python lover already" - exit 0 - elif [ "${elem}" = "/usr/bin" ]; then - break - fi -done - -echo "${PYTHON_ROOT}/bin is not on your PATH or at least not early enough" case "${BSH}" in *csh) - if [ -f "${HOME}/.tcshrc" ]; then - RC="${HOME}/.tcshrc" - else - RC="${HOME}/.cshrc" - fi - # Create backup copy before patching - if [ -f "${RC}" ]; then - cp -fp "${RC}" "${RC}.pysave" - fi - echo "" >> "${RC}" - echo "# Setting PATH for Python ${PYVER}" >> "${RC}" - echo "# The original version is saved in .cshrc.pysave" >> "${RC}" - echo "set path=(${PYTHON_ROOT}/bin "'$path'")" >> "${RC}" - if [ `id -ur` = 0 ]; then - chown -h "${USER}" "${RC}" - fi - exit 0 - ;; + if [ -f "${HOME}/.tcshrc" ]; then + RC="${HOME}/.tcshrc" + else + RC="${HOME}/.cshrc" + fi + + # Drop privileges while writing files. + su -m ${USER} <> "${RC}" + echo "# Setting PATH for Python ${PYVER}" >> "${RC}" + echo "# The original version is saved in .cshrc.pysave" >> "${RC}" + echo "set path=(${PYTHON_ROOT}/bin "'$path'")" >> "${RC}" +EOFC + + if [ `id -ur` = 0 ]; then + chown -h "${USER}" "${RC}" + fi + exit 0 + ;; bash) - if [ -e "${HOME}/.bash_profile" ]; then - PR="${HOME}/.bash_profile" - elif [ -e "${HOME}/.bash_login" ]; then - PR="${HOME}/.bash_login" - elif [ -e "${HOME}/.profile" ]; then - PR="${HOME}/.profile" - else - PR="${HOME}/.bash_profile" - fi - ;; + if [ -e "${HOME}/.bash_profile" ]; then + PR="${HOME}/.bash_profile" + elif [ -e "${HOME}/.bash_login" ]; then + PR="${HOME}/.bash_login" + elif [ -e "${HOME}/.profile" ]; then + PR="${HOME}/.profile" + else + PR="${HOME}/.bash_profile" + fi + ;; fish) - CONFIG_DIR="${HOME}/.config/fish/conf.d/" - RC="${CONFIG_DIR}/python-${PYVER}.fish" - mkdir -p "$CONFIG_DIR" - if [ -f "${RC}" ]; then - cp -fp "${RC}" "${RC}.pysave" - fi - echo "# Setting PATH for Python ${PYVER}" > "${RC}" - if [ -f "${RC}.pysave" ]; then - echo "# The original version is saved in ${RC}.pysave" >> "${RC}" - fi - echo "fish_add_path -g \"${PYTHON_ROOT}/bin\"" >> "${RC}" - if [ `id -ur` = 0 ]; then - chown -h "${USER}" "${RC}" - fi - exit 0 - ;; + CONFIG_DIR="${HOME}/.config/fish/conf.d/" + RC="${CONFIG_DIR}/python-${PYVER}.fish" + + # Drop privileges while writing files. + su -m ${USER} < "${RC}" + if [ -f "${RC}.pysave" ]; then + echo "# The original version is saved in ${RC}.pysave" >> "${RC}" + fi + echo "fish_add_path -g \"${PYTHON_ROOT}/bin\"" >> "${RC}" +EOFF + + if [ `id -ur` = 0 ]; then + chown -h "${USER}" "${RC}" + fi + exit 0 + ;; zsh) - PR="${HOME}/.zprofile" - ;; + PR="${HOME}/.zprofile" + ;; *sh) - PR="${HOME}/.profile" - ;; + PR="${HOME}/.profile" + ;; esac +# Drop privileges while writing files. +su -m ${USER} <> "${PR}" echo "# Setting PATH for Python ${PYVER}" >> "${PR}" echo "# The original version is saved in `basename ${PR}`.pysave" >> "${PR}" echo 'PATH="'"${PYTHON_ROOT}/bin"':${PATH}"' >> "${PR}" echo 'export PATH' >> "${PR}" +EOFS + if [ `id -ur` = 0 ]; then - chown -h "${USER}" "${PR}" + chown -h "${USER}" "${PR}" fi exit 0 From c3ae7e7108e38b4cdd783ad23e21cdd2cb673e17 Mon Sep 17 00:00:00 2001 From: Ned Deily Date: Wed, 6 Aug 2025 05:26:36 -0400 Subject: [PATCH 3/6] remove set -e to avoid install failure --- Mac/BuildScript/scripts/postflight.patch-profile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Mac/BuildScript/scripts/postflight.patch-profile b/Mac/BuildScript/scripts/postflight.patch-profile index 1cca8eb0252d988..f20fdbd9d1619c8 100755 --- a/Mac/BuildScript/scripts/postflight.patch-profile +++ b/Mac/BuildScript/scripts/postflight.patch-profile @@ -3,7 +3,6 @@ PYVER=@PYVER@ PYTHON_ROOT="/Library/Frameworks/Python.framework/Versions/@PYVER@" -set -e # Run from the installer, do some trickery to fetch the information # we need. @@ -30,7 +29,6 @@ case "${BSH}" in # Drop privileges while writing files. su -m ${USER} < Date: Wed, 6 Aug 2025 05:58:42 -0400 Subject: [PATCH 4/6] do not expand $PATH when writing --- Mac/BuildScript/scripts/postflight.patch-profile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mac/BuildScript/scripts/postflight.patch-profile b/Mac/BuildScript/scripts/postflight.patch-profile index f20fdbd9d1619c8..ce8720f895d1b5c 100755 --- a/Mac/BuildScript/scripts/postflight.patch-profile +++ b/Mac/BuildScript/scripts/postflight.patch-profile @@ -36,7 +36,7 @@ case "${BSH}" in echo "" >> "${RC}" echo "# Setting PATH for Python ${PYVER}" >> "${RC}" echo "# The original version is saved in .cshrc.pysave" >> "${RC}" - echo "set path=(${PYTHON_ROOT}/bin "'$path'")" >> "${RC}" + echo "set path=(${PYTHON_ROOT}/bin "'\$path'")" >> "${RC}" EOFC if [ `id -ur` = 0 ]; then @@ -94,7 +94,7 @@ fi echo "" >> "${PR}" echo "# Setting PATH for Python ${PYVER}" >> "${PR}" echo "# The original version is saved in `basename ${PR}`.pysave" >> "${PR}" -echo 'PATH="'"${PYTHON_ROOT}/bin"':${PATH}"' >> "${PR}" +echo 'PATH="'"${PYTHON_ROOT}/bin"':\${PATH}"' >> "${PR}" echo 'export PATH' >> "${PR}" EOFS From 064a39723fe69ee1b21a562267b8ee6f516bc0f2 Mon Sep 17 00:00:00 2001 From: Ned Deily Date: Wed, 6 Aug 2025 06:29:34 -0400 Subject: [PATCH 5/6] add blurb --- .../next/macOS/2025-08-06-06-29-12.gh-issue-137450.JZypb7.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/macOS/2025-08-06-06-29-12.gh-issue-137450.JZypb7.rst diff --git a/Misc/NEWS.d/next/macOS/2025-08-06-06-29-12.gh-issue-137450.JZypb7.rst b/Misc/NEWS.d/next/macOS/2025-08-06-06-29-12.gh-issue-137450.JZypb7.rst new file mode 100644 index 000000000000000..c9be32205ec1c3c --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2025-08-06-06-29-12.gh-issue-137450.JZypb7.rst @@ -0,0 +1,3 @@ +macOS installer shell path management improvements: separate the installer +`Shell profile updater` postinstall script from the `Update Shell +Profile.command` to enable more robust error handling. From 23f3ff6f7073cfc7ee684bd5c164b639c583960f Mon Sep 17 00:00:00 2001 From: Ned Deily Date: Wed, 6 Aug 2025 06:52:39 -0400 Subject: [PATCH 6/6] Fix literals in blurb --- .../next/macOS/2025-08-06-06-29-12.gh-issue-137450.JZypb7.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/macOS/2025-08-06-06-29-12.gh-issue-137450.JZypb7.rst b/Misc/NEWS.d/next/macOS/2025-08-06-06-29-12.gh-issue-137450.JZypb7.rst index c9be32205ec1c3c..5efd74660c95d20 100644 --- a/Misc/NEWS.d/next/macOS/2025-08-06-06-29-12.gh-issue-137450.JZypb7.rst +++ b/Misc/NEWS.d/next/macOS/2025-08-06-06-29-12.gh-issue-137450.JZypb7.rst @@ -1,3 +1,3 @@ macOS installer shell path management improvements: separate the installer -`Shell profile updater` postinstall script from the `Update Shell -Profile.command` to enable more robust error handling. +``Shell profile updater`` postinstall script from the +``Update Shell Profile.command`` to enable more robust error handling.