# Entry point for the bug-report collector under PowerShell, so agents and people start it # through the same string on every platform: # # tools/bugreport [options] # # PowerShell resolves that to this file first. Without it, `tools/bugreport` is the sh # launcher next to it, which PowerShell does not run. The POSIX half - Linux, macOS and # Git Bash - is tools/bugreport. # # Same rules as the sh twin: tools/bugreport.py has to run when nothing else does, so # nothing the preflight sets up is assumed. The Python is looked for the way the preflight # looks - on Windows python, py -3, python3; elsewhere python3, python; every match on PATH # in PATH order, on Windows with the registry's PATH added for a session that started # before the install - and only then in the venv. Nothing under WindowsApps is ever started: # python.exe and python3.exe there are the Microsoft Store's aliases. Every candidate is # probed first, so one that is too old or refused (a venv python.exe blocked by Defender) is # passed over rather than ending the report. Without any Python 3.8 or newer it says so and # exits 1, never 42: the collector opens no gate. # # There is no `#Requires -Version 7`: someone who needs a bug report should not fail at the # shell's version first, so this file keeps to what Windows PowerShell 5.1 understands too. # # CHEMENU_PREFLIGHT_PLATFORM stands in for the platform, as it does for the preflight; the # test suite is its only user. $ErrorActionPreference = 'Stop' $PSNativeCommandArgumentPassing = 'Standard' $Dir = $PSScriptRoot $Collector = Join-Path $Dir 'bugreport.py' $Min = '3.8' # Exit 3 marks "a Python, but too old" apart from "did not start at all". $Probe = 'import sys; sys.exit(0 if sys.version_info >= (3, 8) else 3)' $Platform = $env:CHEMENU_PREFLIGHT_PLATFORM if (-not $Platform) { if ($env:OS -eq 'Windows_NT') { $Platform = 'windows' } else { $Platform = 'other' } } if ($Platform -eq 'windows') { $Order = @(@('python', @()), @('py', @('-3')), @('python3', @())) $Looked = 'python, py -3, python3' } else { $Order = @(@('python3', @()), @('python', @())) $Looked = 'python3, python' } function Test-StoreAlias { param([string]$Path) return $Path -match '(?i)[\\/]windowsapps[\\/]' } # PATH as this process has it, plus - on Windows - what the registry holds that a # long-running session has not picked up yet. function Get-SearchDirectory { $directories = New-Object System.Collections.Generic.List[string] $sources = @($env:PATH) if ($env:OS -eq 'Windows_NT') { foreach ($scope in 'Machine', 'User') { $sources += [Environment]::GetEnvironmentVariable('Path', $scope) } } foreach ($source in $sources) { if (-not $source) { continue } foreach ($entry in $source.Split([IO.Path]::PathSeparator)) { $expanded = [Environment]::ExpandEnvironmentVariables($entry.Trim()) if ($expanded -and -not $directories.Contains($expanded)) { $directories.Add($expanded) } } } return $directories } # Every file called on PATH, in PATH order, store aliases dropped. function Find-OnPath { param([string]$Name) $found = @() foreach ($directory in (Get-SearchDirectory)) { foreach ($file in @($Name, "$Name.exe")) { $candidate = Join-Path $directory $file if ((Test-Path -LiteralPath $candidate -PathType Leaf) -and -not (Test-StoreAlias $candidate)) { $found += $candidate } } } return $found } $script:TooOld = @() # 0 when this Python is 3.8 or newer; anything else when it is not, or did not start. function Test-Python { param([string]$Path, [string[]]$Extra) try { & $Path @Extra -c $Probe *> $null $status = $LASTEXITCODE } catch { return $false } if ($status -eq 3) { $script:TooOld += $Path } return $status -eq 0 } $Python = '' $PythonExtra = @() foreach ($candidate in $Order) { foreach ($path in (Find-OnPath $candidate[0])) { if (Test-Python $path $candidate[1]) { $Python = $path $PythonExtra = $candidate[1] break } } if ($Python) { break } } if (-not $Python) { foreach ($venv in @((Join-Path $Dir '.venv/Scripts/python.exe'), (Join-Path $Dir '.venv/bin/python'))) { if ((Test-Path -LiteralPath $venv -PathType Leaf) -and (Test-Python $venv @())) { $Python = $venv break } } } if ($Python) { & $Python @PythonExtra $Collector @args exit $LASTEXITCODE } $message = @( "No Python $Min or newer could be started, so the bug-report collector did not run." "Looked for $Looked on PATH, then the one in tools/.venv. Microsoft Store aliases" 'under WindowsApps are skipped on purpose - they do not run Python.' ) if ($script:TooOld.Count -gt 0) { $message += "Found, but older than ${Min}:" $message += ($script:TooOld | ForEach-Object { " $_" }) } $message += @( '' "Install Python $Min or newer, or start the collector directly with the full path" 'of one that works:' '' ' tools/bugreport.py ' ) [Console]::Error.WriteLine(($message -join [Environment]::NewLine)) exit 1