4343 # corrupt captured output and break pattern matching throughout this script.
4444 unset GREP_OPTIONS GREP_COLOR GREP_COLORS
4545
46+ # Force the C locale so `tr`/`grep`/`sed`/`sort` behave the same on every
47+ # system, and clear other variables which alter tool behavior.
48+ export LC_ALL=C
49+ unset CDPATH POSIXLY_CORRECT TAR_OPTIONS
50+
51+ # Drop out of any inherited Python venv; `deactivate` doesn't exist in this
52+ # process, so strip its $PATH entries and marker variables by hand.
53+ if [ -n " ${VIRTUAL_ENV:- } " ]; then
54+ clean_path=' '
55+ old_ifs=" ${IFS} "
56+ IFS=' :'
57+ for path_entry in $PATH ; do
58+ case " $path_entry " in
59+ " $VIRTUAL_ENV " /bin | " $VIRTUAL_ENV " /Scripts) ;;
60+ * ) clean_path=" ${clean_path: +${clean_path} : }${path_entry} " ;;
61+ esac
62+ done
63+ IFS=" ${old_ifs} "
64+ PATH=" ${clean_path} "
65+ export PATH
66+ unset VIRTUAL_ENV VIRTUAL_ENV_PROMPT clean_path old_ifs path_entry
67+ fi
68+
69+ # Wipe all PYTHON* variables (keeping PYTHON_TARGET_VERSION, which this
70+ # script uses) so the user's Python settings can't leak into the
71+ # interpreters and builds managed by `uv`.
72+ saved_python_target_version=" ${PYTHON_TARGET_VERSION:- } "
73+ for env_var_name in $( env | LC_ALL=C sed -n ' s/^\(PYTHON[A-Za-z0-9_]*\)=.*/\1/p' ) ; do
74+ unset " $env_var_name " 2> /dev/null || true
75+ done
76+ [ -z " $saved_python_target_version " ] || export PYTHON_TARGET_VERSION=" $saved_python_target_version "
77+ unset saved_python_target_version env_var_name
78+ export PYTHONNOUSERSITE=1
79+
80+ # Clear conda/pip/uv overrides which would affect dependency resolution or
81+ # builds; proxy, TLS, and index/mirror variables stay for corporate networks.
82+ unset CONDA_PREFIX CONDA_DEFAULT_ENV
83+ unset PIP_REQUIRE_VIRTUALENV PIP_TARGET PIP_PREFIX PIP_USER
84+ unset SETUPTOOLS_USE_DISTUTILS
85+ unset UV_NO_BUILD_ISOLATION UV_OFFLINE UV_NO_INDEX \
86+ UV_CONSTRAINT UV_BUILD_CONSTRAINT UV_OVERRIDE \
87+ UV_SYSTEM_PYTHON UV_NO_MANAGED_PYTHON
88+
4689 BOOTSTRAP_TMPDIR=" $( mktemp -d /tmp/qmk-bootstrap-failure.XXXXXX) "
4790 trap ' rm -rf "$BOOTSTRAP_TMPDIR" >/dev/null 2>&1 || true' EXIT
4891 FAILURE_FILE=" ${BOOTSTRAP_TMPDIR} /fail"
@@ -175,6 +218,15 @@ __EOT__
175218 fi
176219 }
177220
221+ check_release_tag () {
222+ # An empty tag means the GitHub API call failed, usually from rate limiting.
223+ if [ -z " $2 " ]; then
224+ echo " Could not determine the latest $1 release." >&2
225+ echo " If GitHub API rate limits are the cause, set GITHUB_TOKEN to raise them." >&2
226+ exit 1
227+ fi
228+ }
229+
178230 fn_os () {
179231 local os_name=$( echo ${1:- } | tr ' A-Z' ' a-z' )
180232 if [ -z " $os_name " ]; then
@@ -285,6 +337,10 @@ __EOT__
285337 print_package_manager_deps_and_delay () {
286338 get_package_manager_deps | tr ' ' ' \n' | sort | xargs -I' {}' echo " - {}" >&2
287339 exit_if_execution_failed
340+ if [ -n " ${1:- } " ]; then
341+ echo >&2
342+ echo " $1 " >&2
343+ fi
288344 preinstall_delay || exit 1
289345 }
290346
@@ -294,7 +350,11 @@ __EOT__
294350 macos)
295351 if [ -n " $( command -v brew 2> /dev/null || true) " ]; then
296352 echo " It will also install the following system packages using 'brew':" >&2
297- print_package_manager_deps_and_delay
353+ local intel_note=" "
354+ if [ " $( fn_arch) " = " X64" ]; then
355+ intel_note=" NOTE: Homebrew no longer provides pre-built packages for Intel Macs, so some of the above may be built from source. This can take a long time."
356+ fi
357+ print_package_manager_deps_and_delay " $intel_note "
298358
299359 brew update
300360
@@ -308,12 +368,14 @@ __EOT__
308368 fi
309369 done
310370
311- if [ -n " ${existing:- } " ]; then
312- brew upgrade $existing
313- fi
314- if [ -n " ${new:- } " ]; then
315- brew install $new
316- fi
371+ # Homebrew no longer builds Intel macOS bottles (tier 3); when a
372+ # bottle is missing, retry the formula as a source build.
373+ for dep in ${existing:- } ; do
374+ brew upgrade " $dep " || brew upgrade --build-from-source " $dep "
375+ done
376+ for dep in ${new:- } ; do
377+ brew install " $dep " || brew install --build-from-source " $dep "
378+ done
317379 else
318380 echo " Please install 'brew' to continue. See https://brew.sh/ for more information." >&2
319381 exit 1
@@ -437,6 +499,7 @@ __EOT__
437499 install_toolchains () {
438500 # Get the latest toolchain release from https://github.com/qmk/qmk_toolchains
439501 local latest_toolchains_release=$( github_api_call repos/qmk/qmk_toolchains/releases/latest - | grep -oE ' "tag_name": "[^"]+' | grep -oE ' [^"]+$' )
502+ check_release_tag qmk_toolchains " $latest_toolchains_release "
440503 # Download the specific release asset with a matching keyword
441504 local toolchain_url=$( github_api_call repos/qmk/qmk_toolchains/releases/tags/$latest_toolchains_release - | grep -oE ' "browser_download_url": "[^"]+"' | grep -oE ' https://[^"]+' | grep -E " qmk_toolchains-.*$( fn_os) $( fn_arch) " )
442505 if [ -z " $toolchain_url " ]; then
@@ -464,6 +527,7 @@ __EOT__
464527
465528 # Get the latest flashing tools release from https://github.com/qmk/qmk_flashutils
466529 local latest_flashutils_release=$( github_api_call repos/qmk/qmk_flashutils/releases/latest - | grep -oE ' "tag_name": "[^"]+' | grep -oE ' [^"]+$' )
530+ check_release_tag qmk_flashutils " $latest_flashutils_release "
467531 # Download the specific release asset with a matching keyword
468532 local flashutils_url=$( github_api_call repos/qmk/qmk_flashutils/releases/tags/$latest_flashutils_release - | grep -oE ' "browser_download_url": "[^"]+"' | grep -oE ' https://[^"]+' | grep -E " qmk_flashutils-.*$osarchvariant " )
469533 if [ -z " $flashutils_url " ]; then
@@ -486,10 +550,7 @@ __EOT__
486550 install_linux_udev_rules () {
487551 # Get the latest qmk_udev release
488552 local latest_udev_release=$( github_api_call repos/qmk/qmk_udev/releases/latest - | grep -oE ' "tag_name": "[^"]+' | grep -oE ' [^"]+$' )
489- if [ -z " $latest_udev_release " ]; then
490- echo " Could not determine latest qmk_udev release." >&2
491- exit 1
492- fi
553+ check_release_tag qmk_udev " $latest_udev_release "
493554 echo " Using qmk_udev release: $latest_udev_release " >&2
494555
495556 # Download the udev rules file
@@ -541,6 +602,7 @@ __EOT__
541602 install_windows_drivers () {
542603 # Get the latest driver installer release from https://github.com/qmk/qmk_driver_installer
543604 local latest_driver_installer_release=$( github_api_call repos/qmk/qmk_driver_installer/releases/latest - | grep -oE ' "tag_name": "[^"]+' | grep -oE ' [^"]+$' )
605+ check_release_tag qmk_driver_installer " $latest_driver_installer_release "
544606 # Download the specific release asset
545607 local driver_installer_url=$( github_api_call repos/qmk/qmk_driver_installer/releases/tags/$latest_driver_installer_release - | grep -oE ' "browser_download_url": "[^"]+"' | grep -oE ' https://[^"]+' | grep ' \.exe' )
546608 if [ -z " $driver_installer_url " ]; then
@@ -600,7 +662,14 @@ __EOT__
600662 setup_paths
601663
602664 # Work out where we want to install the distribution and tools now that `uv` is installed
603- export QMK_DISTRIB_DIR=" $( posix_ish_path " ${QMK_DISTRIB_DIR:- $(printf ' import platformdirs\nprint(platformdirs.user_data_dir("qmk"))' | uv_command run --quiet --python $PYTHON_TARGET_VERSION --with platformdirs -)} " ) "
665+ export QMK_DISTRIB_DIR=" $( posix_ish_path " ${QMK_DISTRIB_DIR:- $(printf ' import platformdirs\nprint(platformdirs.user_data_dir("qmk"))' | uv_command run --quiet --no-project --python $PYTHON_TARGET_VERSION --with platformdirs -)} " ) "
666+
667+ # `export` masks any failure of the `uv` invocation above, so bail out here
668+ # rather than continue with an empty directory.
669+ if [ -z " $QMK_DISTRIB_DIR " ]; then
670+ echo " Could not determine the QMK distribution directory." >&2
671+ exit 1
672+ fi
604673
605674 # Clear out the distrib directory if necessary
606675 if [ -z " ${SKIP_CLEAN:- } " ] || [ -z " ${SKIP_QMK_TOOLCHAINS:- } " -a -z " ${SKIP_QMK_FLASHUTILS:- } " ]; then
0 commit comments