| :<<"::WINDOWS_ONLY" |
| @echo off |
| :: Copyright 2023 The Pigweed Authors |
| :: |
| :: Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| :: use this file except in compliance with the License. You may obtain a copy of |
| :: the License at |
| :: |
| :: https://www.apache.org/licenses/LICENSE-2.0 |
| :: |
| :: Unless required by applicable law or agreed to in writing, software |
| :: distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| :: WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| :: License for the specific language governing permissions and limitations under |
| :: the License. |
| ::WINDOWS_ONLY |
| :; echo "ERROR: Attempting to run Windows .bat from a Unix/POSIX shell!" |
| :; echo "Instead, run the following command." |
| :; echo "" |
| :; echo " source ./bootstrap.sh" |
| :; echo "" |
| :<<"::WINDOWS_ONLY" |
| |
| :: Utility for bootstrapping Windows dependencies. |
| :: |
| :: This tool does the following: |
| :: - Ensures `winget` is available and ready to use. |
| :: - Ensures developer mode is enabled so symlinks work. |
| :: - Ensures git is set up and ready to go. |
| :: - Ensures a working version of Python is installed. |
| :: - Ensures git is configured to allow symlinks. |
| :: |
| :: Usage: |
| :: setup_windows_prerequisites.bat [mode] |
| :: |
| :: [mode]: Either "check" or "setup" (defaults to "setup" if not specified). |
| :: If set to "check", the script will terminate when it finds |
| :: something to be missing or misconfigured, and emit a helpful |
| :: error message rather than trying to automatically fix the issue. |
| |
| :: WARNING: Multi-line "if" statements can be dangerous! |
| :: |
| :: Example: |
| :: call do_foo |
| :: if [expression] ( |
| :: call cmd_a |
| :: set my_var = %ERRORLEVEL% |
| :: call final_script --flag %my_var% |
| :: ) |
| :: Batch evaluates these expressions in a way that will produce unexpected |
| :: behavior. It appears that when each line is executed, it does not affect |
| :: local context until the entire expression is complete. In this example, |
| :: ERRORLEVEL does not reflect `call cmd_a`, but whatever residual state was |
| :: present from `do_foo`. Similarly, in the call to `final_script`, `my_var` |
| :: will NOT be valid as the variable `set` doesn't apply until the entire `if` |
| :: expression completes. |
| :: This script only uses multi-line if statements to `goto` after an operation. |
| |
| SETLOCAL |
| |
| SET _COLORED_TEXT_OK=[92mOK![0m |
| SET _COLORED_TEXT_MISSING=[93mMISSING![0m |
| SET _COLORED_TEXT_FAIL=[91mFAIL![0m |
| |
| SET _COLORED_TEXT_INSTALL_SUCCEEDED=[92mInstall succeeded![0m |
| SET _COLORED_TEXT_INSTALL_FAILED=[91mInstall failed![0m |
| |
| SET _COLORED_TEXT_DONE="[92mDONE![0m " |
| SET _COLORED_TEXT_NOTE="[93mNOTE:[0m " |
| SET _COLORED_TEXT_ERROR="[91mERROR:[0m " |
| |
| SET "_DEV_MODE_PATH=Settings->Update & Security->For developers->Developer Mode" |
| |
| reg query HKLM\Software\Policies\Microsoft\Windows\Appx /v BlockNonAdminUserInstall | find "0x1" >NUL 2>&1 |
| SET /a "_BLOCK_NON_ADMIN_USER_INSTALL_ENABLED=%ERRORLEVEL%" >NUL 2>&1 |
| |
| :ensure_minimum_requirements |
| SET mode=INVALID |
| IF "%1"=="" set mode=SETUP |
| IF "%1"=="check" set mode=CHECK |
| IF "%1"=="setup" set mode=SETUP |
| |
| CALL :ensure_winget_permissions %mode% |
| IF %ERRORLEVEL% NEQ 0 GOTO abort |
| |
| CALL :ensure_winget %mode% |
| IF %ERRORLEVEL% NEQ 0 GOTO abort |
| |
| CALL :ensure_symlinks %mode% |
| IF %ERRORLEVEL% NEQ 0 GOTO abort |
| |
| CALL :ensure_git %mode% |
| IF %ERRORLEVEL% NEQ 0 GOTO abort |
| |
| CALL :ensure_python %mode% |
| IF %ERRORLEVEL% NEQ 0 GOTO abort |
| |
| CALL :ensure_git_symlinks %mode% |
| IF %ERRORLEVEL% NEQ 0 GOTO abort |
| |
| CALL :ensure_long_paths %mode% |
| IF %ERRORLEVEL% NEQ 0 GOTO abort |
| |
| echo | SET /p=%_COLORED_TEXT_DONE% |
| |
| :: Workaround until winget properly updates PATH after installations. |
| :: https://github.com/microsoft/winget-cli/issues/222 |
| :: Note: This "start" doesn't work, it just looks nice for now. You actually |
| :: need to restart the command prompt by hand. |
| SET "local_path=%PATH%" |
| IF "%mode%"=="SETUP" ( |
| echo Everything is ready to go! |
| echo. |
| echo %_COLORED_TEXT_NOTE% We advise opening a fresh shell before running bootstrap.bat! |
| endlocal & set "PATH=%local_path%" |
| ) |
| |
| IF "%mode%"=="CHECK" ( |
| echo Everything is ready to go! |
| ) |
| |
| EXIT /B 0 |
| |
| :abort |
| :: TODO: add flag to restore previous permissions after. |
| rem CALL :restore_winget_permissions %mode%, %_BLOCK_NON_ADMIN_USER_INSTALL_ENABLED% |
| echo Failed to bootstrap development environment. Exiting... |
| EXIT /B %ERRORLEVEL% |
| |
| :: Checks if winget has been bootstrapped, setting it up if not. |
| :: |
| :: Arguments: |
| :: %~1: "CHECK" or "SETUP" |
| :: |
| :: Returns: |
| :: 0 if winget is available and ready to use. |
| :ensure_winget |
| :: First call is to see if we need winget. |
| CALL :check_winget %~1 |
| IF %ERRORLEVEL% EQU 0 EXIT /B 0 |
| |
| :: If CHECK mode, return here. |
| IF "%~1"=="CHECK" EXIT /B %ERRORLEVEL% |
| |
| :: winget check failed, try to bootstrap. |
| echo %_COLORED_TEXT_MISSING% |
| CALL :bootstrap_winget |
| IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% |
| |
| EXIT /B %ERRORLEVEL% |
| |
| :: Checks if winget is present. |
| :: |
| :: Arguments: |
| :: %~1: "CHECK" or "SETUP", controls soft vs hard failures. |
| :: |
| :: Returns: |
| :: 0 if a functional system Python is available. |
| :check_winget |
| echo | SET /p="Checking for winget..........." |
| where winget >NUL 2>&1 |
| IF "%~1"=="CHECK" CALL :pretty_print_failure %ERRORLEVEL%, "winget does not exist." |
| IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% |
| |
| winget --version >NUL 2>&1 |
| IF "%~1"=="CHECK" CALL :pretty_print_failure %ERRORLEVEL%, "winget isn't working as expected, check your internet connection or firewall settings." |
| IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% |
| |
| echo %_COLORED_TEXT_OK% |
| EXIT /B 0 |
| |
| :: Try to bootstrap winget. |
| :: |
| :: Arguments: |
| :: None. |
| :: |
| :: Returns: |
| :: 0 if winget is properly set up. |
| :bootstrap_winget |
| echo | SET /p="Bootstrapping winget.........." |
| |
| echo Add-AppxPackage -RegisterByFamilyName -MainPackage Microsoft.DesktopAppInstaller_8wekyb3d8bbwe>%TEMP%\install_winget.ps1 2>&1 |
| SET /a "retval=!%ERRORLEVEL%" >NUL 2>&1 |
| CALL :pretty_print_failure %retval%, "Failed to create winget install script." |
| IF %retval% NEQ 0 EXIT /B %retval% |
| powershell -command "Start -Verb RunAs -Wait powershell.exe %TEMP%\install_winget.ps1" 2>&1 |
| SET /a "retval=!%ERRORLEVEL%" >NUL 2>&1 |
| CALL :pretty_print_failure %retval%, "Failed to bootstrap winget." |
| del %TEMP%\install_winget.ps1 |
| IF %retval% NEQ 0 EXIT /B %retval% |
| |
| CALL :run_as_admin "winget", "source reset --force" |
| CALL :pretty_print_failure %ERRORLEVEL%, "Failed to refresh winget sources." |
| IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% |
| |
| echo %_COLORED_TEXT_OK% |
| EXIT /B 0 |
| |
| :: Checks if winget sufficient permissions, and tries to enable them if not. |
| :: |
| :: Arguments: |
| :: %~1: "CHECK" or "SETUP" |
| :: |
| :: Returns: |
| :: 0 if winget is available and ready to use. |
| :ensure_winget_permissions |
| :: First call is to see if we need winget. |
| CALL :check_winget_permissions %~1 |
| IF %ERRORLEVEL% EQU 0 EXIT /B 0 |
| |
| :: If CHECK mode, return here. |
| IF "%~1"=="CHECK" EXIT /B %ERRORLEVEL% |
| |
| :: winget check failed, try to bootstrap. |
| echo %_COLORED_TEXT_MISSING% |
| CALL :enable_winget_permissions |
| IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% |
| |
| EXIT /B %ERRORLEVEL% |
| |
| :: Checks if winget installs have permission to succeed. |
| :: |
| :: Arguments: |
| :: %~1: "CHECK" or "SETUP", controls soft vs hard failures. |
| :: |
| :: Returns: |
| :: 0 if sufficient permissions. |
| :check_winget_permissions |
| echo | SET /p="Checking winget install permissions.........." |
| :: This entry must NOT be set. |
| reg query HKLM\Software\Policies\Microsoft\Windows\Appx /v BlockNonAdminUserInstall | find "0x1" >NUL 2>&1 |
| SET /a "retval=!%ERRORLEVEL%" >NUL 2>&1 |
| IF "%~1"=="CHECK" CALL :pretty_print_failure %retval%, "The registry value `BlockNonAdminUserInstall` at HKLM\Software\Policies\Microsoft\Windows\Appx is set to 1, which will prevent winget installs." |
| IF %retval% NEQ 0 EXIT /B %retval% |
| |
| echo %_COLORED_TEXT_OK% |
| EXIT /B 0 |
| |
| :: Enables permissions required to do winget installs. |
| :: |
| :: Arguments: |
| :: %~1: "CHECK" or "SETUP", controls soft vs hard failures. |
| :: |
| :: Returns: |
| :: 0 if succesful. |
| :enable_winget_permissions |
| echo | SET /p="Enabling winget install permissions.........." |
| |
| CALL :run_as_admin "reg", "add HKLM\Software\Policies\Microsoft\Windows\Appx /t REG_DWORD /v BlockNonAdminUserInstall /d 0 /f" |
| CALL :pretty_print_failure %ERRORLEVEL%, "Failed to add registry entry" |
| IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% |
| |
| echo %_COLORED_TEXT_OK% |
| EXIT /B 0 |
| |
| :: Restores previous state of winget install permissions. |
| :: |
| :: Arguments: |
| :: %~1: "CHECK" or "SETUP", controls soft vs hard failures. |
| :: %2: 1 if permissions should be reenabled. |
| :: |
| :: Returns: |
| :: 0 if succesful. |
| :restore_winget_permissions |
| IF %2 EQU 0 EXIT /B 0 |
| IF "%~1"=="CHECK" EXIT /B 0 |
| |
| echo | SET /p="Restoring winget install permissions.........." |
| powershell -command "Start -Verb RunAs -Wait -File "reg" -ArgumentList \"add HKLM\Software\Policies\Microsoft\Windows\Appx /t REG_DWORD /v BlockNonAdminUserInstall /d 1 /f\"" >NUL 2>&1 |
| CALL :pretty_print_failure %ERRORLEVEL%, "Failed to restore registry entry" |
| IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% |
| |
| echo %_COLORED_TEXT_OK% |
| EXIT /B 0 |
| |
| |
| :: Checks if symlinks work, prompting the user to enable developer mode if not. |
| :: |
| :: Arguments: |
| :: %~1: "CHECK" or "SETUP" |
| :: |
| :: Returns: |
| :: 0 if symlinks are properly set up. |
| :ensure_symlinks |
| |
| :: First call is to see if we need to enable symlinks. |
| CALL :check_symlinks %~1 |
| IF %ERRORLEVEL% EQU 0 EXIT /B 0 |
| |
| :: If CHECK mode, return here. |
| IF "%~1"=="CHECK" EXIT /B %ERRORLEVEL% |
| |
| :: symlink check failed, try to enable. |
| echo %_COLORED_TEXT_MISSING% |
| CALL :enable_developer_mode |
| IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% |
| |
| EXIT /B %ERRORLEVEL% |
| |
| :: Checks if symlinks work. |
| :: |
| :: Arguments: |
| :: None |
| :: |
| :: Returns: |
| :: 0 if symlinks are properly set up. |
| :check_symlinks |
| echo | SET /p="Checking if symlinks are enabled..." |
| echo Test file contents >test_file.txt 2>&1 |
| mklink test_file_link.txt test_file.txt >NUL 2>&1 |
| set retval=%ERRORLEVEL% |
| del test_file.txt |
| IF "%~1"=="CHECK" CALL :pretty_print_failure %retval%, "Symlinks are not enabled, please enable Developer Mode in %_DEV_MODE_PATH%" |
| IF %retval% NEQ 0 EXIT /B %retval% |
| :: Symlink was created, delete it. |
| del test_file_link.txt |
| |
| echo %_COLORED_TEXT_OK% |
| EXIT /B 0 |
| |
| :: Prompt the user to enable developer mode. |
| :: |
| :: Arguments: |
| :: %~1: "CHECK" or "SETUP" |
| :: |
| :: Returns: |
| :: 0 if symlinks are properly set up. |
| :enable_developer_mode |
| echo | SET /p="Enabling symlinks.........." |
| |
| powershell -command "Start -Verb RunAs -Wait -File "reg" -ArgumentList \"add HKLM\Software\Microsoft\Windows\CurrentVersion\AppModelUnlock /t REG_DWORD /v AllowDevelopmentWithoutDevLicense /d 1 /f\"" >NUL 2>&1 |
| CALL :pretty_print_failure %ERRORLEVEL%, "Failed to add registry entry" |
| IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% |
| |
| echo %_COLORED_TEXT_OK% |
| |
| echo Waiting for change to apply. |
| :: TODO: This probably was caused by a race in the powershell command above and |
| :: has probably been fixed since `-Wait` was added. |
| timeout /NOBREAK 5 |
| |
| :: Check again to make sure symlinks now work. |
| CALL :check_symlinks CHECK |
| EXIT /B %ERRORLEVEL% |
| |
| :: Checks if git is present, installing one if it is not. |
| :: |
| :: Arguments: |
| :: %~1: "CHECK" or "SETUP" |
| :: |
| :: Returns: |
| :: 0 if a functional system Python is available. |
| :ensure_git |
| :: First call is to see if we need python. |
| CALL :check_git %~1 |
| IF %ERRORLEVEL% EQU 0 EXIT /B 0 |
| |
| :: If CHECK mode, return here. |
| IF "%~1"=="CHECK" EXIT /B %ERRORLEVEL% |
| |
| :: Git check failed, try to install. |
| echo %_COLORED_TEXT_MISSING% |
| CALL :get_package "git", Git.Git |
| IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% |
| |
| :: Oddly, github is never added to the PATH after installing using wingit. |
| :: https://github.com/microsoft/winget-cli/issues/2815 |
| SET "PATH=%ProgramFiles%\Git\cmd;%PATH%" |
| |
| EXIT /B %ERRORLEVEL% |
| |
| :: Checks if a git is present. |
| :: |
| :: Arguments: |
| :: %~1: "CHECK" or "SETUP", controls soft vs hard failures. |
| :: |
| :: Returns: |
| :: 0 if a functional system Python is available. |
| :check_git |
| echo | SET /p="Checking for git.........." |
| where git >NUL 2>&1 |
| IF "%~1"=="CHECK" CALL :pretty_print_failure %ERRORLEVEL%, "git does not exist." |
| IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% |
| |
| git --version >NUL 2>&1 |
| IF "%~1"=="CHECK" CALL :pretty_print_failure %ERRORLEVEL%, "git isn't working as expected." |
| IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% |
| |
| echo %_COLORED_TEXT_OK% |
| EXIT /B 0 |
| |
| :: Checks if a functional system Python is present, installing one if it is not. |
| :: |
| :: Arguments: |
| :: %~1: "CHECK" or "SETUP" |
| :: |
| :: Returns: |
| :: 0 if a functional system Python is available. |
| :ensure_python |
| :: First call is to see if we need python. |
| CALL :check_python %~1 |
| IF %ERRORLEVEL% EQU 0 EXIT /B 0 |
| |
| :: If CHECK mode, return here. |
| IF "%~1"=="CHECK" EXIT /B %ERRORLEVEL% |
| |
| :: Python check failed, try to install. |
| echo %_COLORED_TEXT_MISSING% |
| CALL :get_package "Python", Python.Python.3.8 |
| IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% |
| |
| SET "PATH=%LOCALAPPDATA%\Programs\Python\Python38;%PATH%" |
| |
| EXIT /B %ERRORLEVEL% |
| |
| :: Checks if a functional system Python is present. |
| :: |
| :: Arguments: |
| :: %~1: "CHECK" or "SETUP", controls soft vs hard failures. |
| :: |
| :: Returns: |
| :: 0 if a functional system Python is available. |
| :check_python |
| echo | SET /p="Checking for Python.........." |
| where python >NUL 2>&1 |
| IF "%~1"=="CHECK" CALL :pretty_print_failure %ERRORLEVEL%, "System python does not exist." |
| IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% |
| |
| python -c 'print("Hello, World!")' >NUL 2>&1 |
| IF "%~1"=="CHECK" CALL :pretty_print_failure %ERRORLEVEL%, "System python is a Windows Store link." |
| IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% |
| |
| echo %_COLORED_TEXT_OK% |
| EXIT /B 0 |
| |
| :: Checks if git symlinks are enabled, and tries to enable them. |
| :: |
| :: Arguments: |
| :: %~1: "CHECK" or "SETUP" |
| :: |
| :: Returns: |
| :: 0 if a git symlinks are enabled. |
| :ensure_git_symlinks |
| :: First call is to see if we need to enable symlinks. |
| CALL :check_git_symlinks %~1 |
| IF %ERRORLEVEL% EQU 0 EXIT /B 0 |
| |
| :: If CHECK mode, return here. |
| IF "%~1"=="CHECK" EXIT /B %ERRORLEVEL% |
| |
| :: git symlink check failed, try to set. |
| echo %_COLORED_TEXT_MISSING% |
| CALL :enable_git_symlinks |
| IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% |
| |
| EXIT /B %ERRORLEVEL% |
| |
| :: Checks if git symlinks are enabled. |
| :: |
| :: Arguments: |
| :: %~1: "CHECK" or "SETUP", controls soft vs hard failures. |
| :: |
| :: Returns: |
| :: 0 if git symlinks are enabled. |
| :check_git_symlinks |
| echo | SET /p="Checking git symlinks.........." |
| git --version >NUL 2>&1 |
| :: Unconditionally fail if we fail here. |
| CALL :pretty_print_failure %ERRORLEVEL%, "git not found, if you just installed it try re-running this script." |
| IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% |
| |
| CALL :check_git_setting "core.symlinks", "true" |
| IF "%~1"=="CHECK" CALL :pretty_print_failure %ERRORLEVEL%, "Git's core.symlinks is not enabled." |
| IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% |
| |
| echo %_COLORED_TEXT_OK% |
| EXIT /B 0 |
| |
| :: Enable git symlinks. |
| :: |
| :: Arguments: |
| :: None. |
| :: |
| :: Returns: |
| :: 0 if symlinks are properly enabled. |
| :enable_git_symlinks |
| echo | SET /p="Enabling git symlinks.........." |
| git config --global core.symlinks true |
| CALL :pretty_print_failure %ERRORLEVEL%, "Failed to enable git symlinks." |
| IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% |
| |
| echo %_COLORED_TEXT_OK% |
| EXIT /B 0 |
| |
| :: Checks if a git setting is set appropriately. |
| :: |
| :: Arguments: |
| :: %~1: Setting name |
| :: %~2: Desired setting value |
| :: |
| :: Returns: |
| :: 0 if the setting has the intended valu. |
| :check_git_setting |
| git config --get %~1 > current_git_setting.txt |
| :: Unconditionally fail if we fail here. |
| set retval=%ERRORLEVEL% |
| IF %ERRORLEVEL% NEQ 0 GOTO check_git_setting_cleanup |
| |
| echo %~2 > desired_git_setting.txt |
| set retval=%ERRORLEVEL% |
| IF %ERRORLEVEL% NEQ 0 GOTO check_git_setting_cleanup |
| |
| :: There will be line ending differences, so enable /w. |
| fc /w current_git_setting.txt desired_git_setting.txt >NUL 2>&1 |
| set retval=%ERRORLEVEL% |
| |
| :check_git_setting_cleanup |
| del current_git_setting.txt >NUL 2>&1 |
| del desired_git_setting.txt >NUL 2>&1 |
| |
| EXIT /B %retval% |
| |
| |
| :: Checks if long file path handling is enabled, and tries to enable it. |
| :: |
| :: Arguments: |
| :: %~1: "CHECK" or "SETUP" |
| :: |
| :: Returns: |
| :: 0 if long path support is enabled. |
| :ensure_long_paths |
| :: First call is to see if we need to enable long path support. |
| CALL :check_long_paths %~1 |
| IF %ERRORLEVEL% EQU 0 EXIT /B 0 |
| |
| :: If CHECK mode, return here. |
| IF "%~1"=="CHECK" EXIT /B %ERRORLEVEL% |
| |
| :: Long path check failed, try to enable. |
| echo %_COLORED_TEXT_MISSING% |
| CALL :enable_long_paths |
| IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% |
| |
| EXIT /B %ERRORLEVEL% |
| |
| |
| :: Checks if long file path support is enabled. |
| :: |
| :: Arguments: |
| :: %~1: "CHECK" or "SETUP", controls soft vs hard failures. |
| :: |
| :: Returns: |
| :: 0 if long paths are enabled. |
| :check_long_paths |
| echo | SET /p="Checking if long paths are enabled.........." |
| reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem /v LongPathsEnabled | find "0x1" >NUL 2>&1 |
| SET /a "retval=%ERRORLEVEL%" >NUL 2>&1 |
| |
| IF "%~1"=="CHECK" CALL :pretty_print_failure %retval%, "The registry value `LongPathsEnabled` at HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem is set to 0, which will cause failures in deeply nested directories." |
| IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% |
| |
| echo %_COLORED_TEXT_OK% |
| EXIT /B 0 |
| |
| |
| :: Enables long path support. |
| :: |
| :: Arguments: |
| :: %~1: "CHECK" or "SETUP", controls soft vs hard failures. |
| :: |
| :: Returns: |
| :: 0 if succesful. |
| :enable_long_paths |
| IF %retval% NEQ 0 CALL :run_as_admin "reg", "add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem /v LongPathsEnabled /t REG_DWORD /d 1 /f" |
| CALL :pretty_print_failure %ERRORLEVEL%, "Failed to enable long paths." |
| IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% |
| |
| echo %_COLORED_TEXT_OK% |
| EXIT /B 0 |
| |
| :: Checks if a functional system Python is present, installing one if it is not. |
| :: |
| :: Arguments: |
| :: %~1: Output text for step |
| :: %~2: Name of winget package |
| :: |
| :: Returns: |
| :: 0 if a functional system Python is available. |
| :get_package |
| echo Installing %~1............ |
| powershell -command "Start -Verb RunAs -Wait -File winget -ArgumentList \"install -e --id %~2 --source winget\"" |
| IF %ERRORLEVEL% EQU 0 ( |
| echo %_COLORED_TEXT_INSTALL_SUCCEEDED% |
| EXIT /B 0 |
| ) |
| |
| set retval=%ERRORLEVEL% |
| echo %_COLORED_TEXT_INSTALL_FAILED% |
| EXIT /B %retval% |
| |
| |
| :: Runs a command as administrator. |
| :: |
| :: Arguments: |
| :: %~1: Command name (string) |
| :: %~2: Command arguments (string) |
| :: |
| :: Returns: |
| :: 0 command succeeded. |
| :run_as_admin |
| powershell -command "$proc=(Start -Verb RunAs -Wait -PassThru -File %~1 -ArgumentList \"%~2\"); exit $proc.ExitCode" |
| EXIT /B %ERRORLEVEL% |
| |
| :: Prints FAIL! and then an error. |
| :: |
| :: Arguments: |
| :: %~1: Return value of the error, so it can propagate. |
| :: %~2: Error message. |
| :: |
| :: Returns: |
| :: %~1: Original error code. |
| :pretty_print_failure |
| IF %~1 NEQ 0 ( |
| echo %_COLORED_TEXT_FAIL% |
| echo | SET /p=%_COLORED_TEXT_ERROR% |
| echo | SET /p "=%~2" |
| echo: |
| ) |
| EXIT /B %~1 |
| |
| :pretty_print_error |
| IF %~1 NEQ 0 ( |
| echo | SET /p=%_COLORED_TEXT_ERROR% |
| echo | SET /p "=%~2" |
| echo: |
| ) |
| EXIT /B %~1 |
| |
| :pretty_print_ok |
| IF %~1 EQU 0 echo %_COLORED_TEXT_OK% |
| EXIT /B %~1 |