Files
Bubberstation/tools/bootstrap/python_.ps1
Tad Hardesty 67b4aa190e Use portable Python for map merge hooks, other tools (#55658)
* Add tools/bootstrap/python

* Add dependencies.sh entry for Python

* Use bootstrapped Python for HitboxExpander

* Use bootstrapped Python when installing hooks

Also:
- Adds tools/hooks/Uninstall.bat
- Removes the need to re-run Install.bat when a .hook file changes

Python path temporarily includes tools/mapmerge2 as before:
- PYTHONPATH in tools/hooks/python.sh handles Linux/virtualenv
- python36._pth handles Windows portable

* Move DMI merge driver to its own directory

* Use bootstrapped Python for makeChangelog.bat

* Set window title in bootstrap PS scripts

* Use slashes in hook paths

* Use relative imports in mapmerge2

* Use bootstrapped Python for mapmerge

* Update mapmerge2 readme

* Skip non-3way conflicts

* Fix relative path issue in posthoc merger

* Add missing call and %* to .bat files

* When installing hooks, don't uninstall them all first

* Make dependencies.sh POSIX

* Move update_paths.py to its own folder

* Use line buffering for Python stdout/stderr

It was switching to fully-buffered mode due to being piped, meaning we
wouldn't see output until the script ended. This is undesirable.

* Use new path to dmi.test in CI suite

* Validate system Python version in bootstrap script

* Add install advice to bootstrap script

* Update path to requirements.txt in CI

* Add upgrader for existing installations
2020-12-22 22:22:15 +01:00

104 lines
3.4 KiB
PowerShell

# bootstrap/python_.ps1
#
# Python bootstrapping script for Windows.
#
# Automatically downloads a portable edition of a pinned Python version to
# a cache directory, installs Pip, installs `requirements.txt`, and then invokes
# Python.
#
# The underscore in the name is so that typing `bootstrap/python` into
# PowerShell finds the `.bat` file first, which ensures this script executes
# regardless of ExecutionPolicy.
$host.ui.RawUI.WindowTitle = "starting :: python $args"
$ErrorActionPreference = "Stop"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Add-Type -AssemblyName System.IO.Compression.FileSystem
function ExtractVersion {
param([string] $Path, [string] $Key)
foreach ($Line in Get-Content $Path) {
if ($Line.StartsWith("export $Key=")) {
return $Line.Substring("export $Key=".Length)
}
}
throw "Couldn't find value for $Key in $Path"
}
# Convenience variables
$Bootstrap = Split-Path $script:MyInvocation.MyCommand.Path
$Tools = Split-Path $Bootstrap
$Cache = "$Bootstrap/.cache"
if ($Env:TG_BOOTSTRAP_CACHE) {
$Cache = $Env:TG_BOOTSTRAP_CACHE
}
$PythonVersion = ExtractVersion -Path "$Bootstrap/../../dependencies.sh" -Key "PYTHON_VERSION"
$PythonDir = "$Cache/python-$PythonVersion"
$PythonExe = "$PythonDir/python.exe"
$Log = "$Cache/last-command.log"
# Download and unzip a portable version of Python
if (!(Test-Path $PythonExe -PathType Leaf)) {
$host.ui.RawUI.WindowTitle = "Downloading Python $PythonVersion..."
New-Item $Cache -ItemType Directory -ErrorAction silentlyContinue | Out-Null
$Archive = "$Cache/python-$PythonVersion-embed.zip"
Invoke-WebRequest `
"https://www.python.org/ftp/python/$PythonVersion/python-$PythonVersion-embed-amd64.zip" `
-OutFile $Archive `
-ErrorAction Stop
[System.IO.Compression.ZipFile]::ExtractToDirectory($Archive, $PythonDir)
# Copy a ._pth file without "import site" commented, so pip will work
Copy-Item "$Bootstrap/python36._pth" $PythonDir `
-ErrorAction Stop
Remove-Item $Archive
}
# Install pip
if (!(Test-Path "$PythonDir/Scripts/pip.exe")) {
$host.ui.RawUI.WindowTitle = "Downloading Pip..."
Invoke-WebRequest "https://bootstrap.pypa.io/get-pip.py" `
-OutFile "$Cache/get-pip.py" `
-ErrorAction Stop
& $PythonExe "$Cache/get-pip.py" --no-warn-script-location
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
Remove-Item "$Cache/get-pip.py" `
-ErrorAction Stop
}
# Use pip to install our requirements
if (!(Test-Path "$PythonDir/requirements.txt") -or ((Get-FileHash "$Tools/requirements.txt").hash -ne (Get-FileHash "$PythonDir/requirements.txt").hash)) {
$host.ui.RawUI.WindowTitle = "Updating dependencies..."
& $PythonExe -m pip install -U pip -r "$Tools/requirements.txt"
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
Copy-Item "$Tools/requirements.txt" "$PythonDir/requirements.txt"
Write-Output "`n---`n"
}
# Invoke python with all command-line arguments
Write-Output $PythonExe | Out-File -Encoding utf8 $Log
[System.String]::Join([System.Environment]::NewLine, $args) | Out-File -Encoding utf8 -Append $Log
Write-Output "---" | Out-File -Encoding utf8 -Append $Log
$host.ui.RawUI.WindowTitle = "python $args"
$ErrorActionPreference = "Continue"
& $PythonExe -u $args 2>&1 | ForEach-Object {
$str = "$_"
if ($_.GetType() -eq [System.Management.Automation.ErrorRecord]) {
$str = $str.TrimEnd("`r`n")
}
$str | Out-File -Encoding utf8 -Append $Log
$str | Out-Host
}
exit $LastExitCode