177 lines
7.1 KiB
PowerShell
177 lines
7.1 KiB
PowerShell
function Ensure-Pnpm {
|
|
Ensure-NodeRuntime
|
|
$dependency = Get-BootstrapDependency -Name 'pnpm'
|
|
$pnpm = Get-NodeCommandPath -Name 'pnpm'
|
|
$currentVersion = ''
|
|
if ($pnpm) {
|
|
$previousErrorActionPreference = $ErrorActionPreference
|
|
try {
|
|
$ErrorActionPreference = 'Continue'
|
|
$versionOutput = @(& $pnpm --version 2>$null)
|
|
$versionExitCode = $LASTEXITCODE
|
|
}
|
|
finally {
|
|
$ErrorActionPreference = $previousErrorActionPreference
|
|
}
|
|
$versionLine = $versionOutput | Select-Object -First 1
|
|
if ($versionExitCode -eq 0 -and $null -ne $versionLine) {
|
|
$currentVersion = ([string]$versionLine).Trim()
|
|
}
|
|
}
|
|
if ($currentVersion -ne [string]$dependency.version) {
|
|
$npm = Get-NodeCommandPath -Name 'npm'
|
|
if ([string]::IsNullOrWhiteSpace($npm)) {
|
|
throw 'npm is not available after Node.js installation.'
|
|
}
|
|
& $npm install -g ([string]$dependency.package)
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Failed to install pinned pnpm dependency $($dependency.package)."
|
|
}
|
|
}
|
|
}
|
|
|
|
function Assert-GitCheckoutState {
|
|
param(
|
|
[Parameter(Mandatory = $true)][string]$GitPath,
|
|
[Parameter(Mandatory = $true)][string]$CheckoutPath,
|
|
[Parameter(Mandatory = $true)][string]$PinnedCommit
|
|
)
|
|
|
|
$previousErrorActionPreference = $ErrorActionPreference
|
|
try {
|
|
$ErrorActionPreference = 'Continue'
|
|
$resolvedOutput = @(& $GitPath -C $CheckoutPath rev-parse HEAD 2>$null)
|
|
$resolveExitCode = $LASTEXITCODE
|
|
}
|
|
finally {
|
|
$ErrorActionPreference = $previousErrorActionPreference
|
|
}
|
|
$resolvedLine = $resolvedOutput | Select-Object -First 1
|
|
$resolvedCommit = if ($null -eq $resolvedLine) { '' } else { ([string]$resolvedLine).Trim() }
|
|
if ($resolveExitCode -ne 0 -or $resolvedCommit -ne $PinnedCommit) {
|
|
throw "Checkout verification failed: expected $PinnedCommit, got $resolvedCommit ($CheckoutPath)"
|
|
}
|
|
try {
|
|
$ErrorActionPreference = 'Continue'
|
|
$status = @(& $GitPath -C $CheckoutPath status --porcelain --untracked-files=all 2>$null)
|
|
$statusExitCode = $LASTEXITCODE
|
|
}
|
|
finally {
|
|
$ErrorActionPreference = $previousErrorActionPreference
|
|
}
|
|
if ($statusExitCode -ne 0) {
|
|
throw "Cannot inspect checkout state: $CheckoutPath"
|
|
}
|
|
if ($status.Count -gt 0) {
|
|
throw "Checkout has local changes; refusing to execute it: $CheckoutPath"
|
|
}
|
|
}
|
|
|
|
function Move-BootstrapDirectory {
|
|
param(
|
|
[Parameter(Mandatory = $true)][string]$Source,
|
|
[Parameter(Mandatory = $true)][string]$Destination
|
|
)
|
|
[IO.Directory]::Move($Source, $Destination)
|
|
}
|
|
|
|
function Ensure-GitCloneInstall {
|
|
param(
|
|
[Parameter(Mandatory = $true)]$Definition,
|
|
[Parameter(Mandatory = $true)][string]$TargetPath
|
|
)
|
|
|
|
$git = Get-FirstCommandPath -Names @('git')
|
|
if ([string]::IsNullOrWhiteSpace($git)) {
|
|
throw 'git is required for git-clone bootstrap definitions.'
|
|
}
|
|
|
|
$pinnedCommit = if ($Definition.PSObject.Properties['pinnedCommit']) { [string]$Definition.pinnedCommit } else { '' }
|
|
if ([string]::IsNullOrWhiteSpace($pinnedCommit)) {
|
|
throw "Git capability $($Definition.repo) must define pinnedCommit."
|
|
}
|
|
|
|
if ((Test-Path -LiteralPath $TargetPath -PathType Container) -and (Test-Path -LiteralPath (Join-Path $TargetPath '.git'))) {
|
|
Assert-GitCheckoutState -GitPath $git -CheckoutPath $TargetPath -PinnedCommit $pinnedCommit
|
|
return $true
|
|
}
|
|
if (Test-Path -LiteralPath $TargetPath) {
|
|
throw "Install path exists but is not a git checkout: $TargetPath"
|
|
}
|
|
|
|
$parent = Split-Path -Path $TargetPath -Parent
|
|
Ensure-DownloadDirectory -Path $parent
|
|
$stagePath = Join-Path $parent ('.reverse-bootstrap-{0}' -f [Guid]::NewGuid().ToString('N'))
|
|
New-Item -ItemType Directory -Path $stagePath | Out-Null
|
|
try {
|
|
& $git init --quiet $stagePath
|
|
if ($LASTEXITCODE -ne 0) { throw 'git init failed' }
|
|
& $git -C $stagePath remote add origin $Definition.repo
|
|
if ($LASTEXITCODE -ne 0) { throw 'git remote add failed' }
|
|
& $git -C $stagePath fetch --depth 1 origin $pinnedCommit
|
|
if ($LASTEXITCODE -ne 0) { throw 'git fetch failed' }
|
|
& $git -C $stagePath checkout --quiet --detach FETCH_HEAD
|
|
if ($LASTEXITCODE -ne 0) { throw 'git checkout failed' }
|
|
Assert-GitCheckoutState -GitPath $git -CheckoutPath $stagePath -PinnedCommit $pinnedCommit
|
|
Move-BootstrapDirectory -Source $stagePath -Destination $TargetPath
|
|
if (-not (Test-Path -LiteralPath (Join-Path $TargetPath '.git') -PathType Container)) {
|
|
throw "Failed to promote staged checkout to $TargetPath"
|
|
}
|
|
}
|
|
finally {
|
|
if (Test-Path -LiteralPath $stagePath) {
|
|
Remove-Item -LiteralPath $stagePath -Recurse -Force
|
|
}
|
|
}
|
|
|
|
return $true
|
|
}
|
|
|
|
function Invoke-AnythingAnalyzerPinnedInstall {
|
|
param(
|
|
[Parameter(Mandatory = $true)][string]$RepoDir,
|
|
[Parameter(Mandatory = $true)][string]$PnpmPath,
|
|
[Parameter(Mandatory = $true)][string]$GitPath,
|
|
[Parameter(Mandatory = $true)][string]$PinnedCommit,
|
|
[string]$VsBuildToolsError = ''
|
|
)
|
|
|
|
$workspacePath = Join-Path $RepoDir 'pnpm-workspace.yaml'
|
|
$workspaceExisted = Test-Path -LiteralPath $workspacePath -PathType Leaf
|
|
$workspaceBytes = if ($workspaceExisted) { [IO.File]::ReadAllBytes($workspacePath) } else { $null }
|
|
|
|
Push-Location $RepoDir
|
|
try {
|
|
Approve-AnythingAnalyzerBuildScripts -RepoDir $RepoDir
|
|
if (-not (Test-AnythingAnalyzerElectronHealthy -RepoDir $RepoDir -PnpmPath $PnpmPath)) {
|
|
$nodeModules = Join-Path $RepoDir 'node_modules'
|
|
Remove-Item -LiteralPath $nodeModules -Recurse -Force -ErrorAction SilentlyContinue
|
|
}
|
|
|
|
& $PnpmPath install --frozen-lockfile
|
|
if ($LASTEXITCODE -ne 0) {
|
|
if ($VsBuildToolsError) { throw "pnpm install failed for anything-analyzer. Visual Studio Build Tools auto-install also failed earlier: $VsBuildToolsError" }
|
|
throw 'pnpm install failed for anything-analyzer.'
|
|
}
|
|
& $PnpmPath rebuild electron esbuild better-sqlite3
|
|
if ($LASTEXITCODE -ne 0) {
|
|
if ($VsBuildToolsError) { throw "pnpm rebuild failed for anything-analyzer. Visual Studio Build Tools auto-install also failed earlier: $VsBuildToolsError" }
|
|
throw 'pnpm rebuild failed for anything-analyzer.'
|
|
}
|
|
if (-not (Test-AnythingAnalyzerElectronHealthy -RepoDir $RepoDir -PnpmPath $PnpmPath)) {
|
|
throw 'anything-analyzer Electron dependency is still unhealthy after pnpm rebuild.'
|
|
}
|
|
}
|
|
finally {
|
|
Pop-Location
|
|
if ($workspaceExisted) {
|
|
[IO.File]::WriteAllBytes($workspacePath, $workspaceBytes)
|
|
}
|
|
elseif (Test-Path -LiteralPath $workspacePath) {
|
|
Remove-Item -LiteralPath $workspacePath -Force
|
|
}
|
|
}
|
|
|
|
Assert-GitCheckoutState -GitPath $GitPath -CheckoutPath $RepoDir -PinnedCommit $PinnedCommit
|
|
}
|