Private/Logic/RuntimeKernel/Facts/Manifested.RuntimeFacts.Collectors.ps1
|
function Test-ManifestedNpmCliRuntimeHome { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [pscustomobject]$Definition, [Parameter(Mandatory = $true)] [string]$RuntimeHome ) $factsBlock = Get-ManifestedDefinitionBlock -Definition $Definition -SectionName 'facts' -BlockName 'npmCli' $commandFileName = if ($factsBlock.PSObject.Properties.Match('commandFileName').Count -gt 0) { $factsBlock.commandFileName } else { $null } $packageJsonRelativePath = if ($factsBlock.PSObject.Properties.Match('packageJsonRelativePath').Count -gt 0) { $factsBlock.packageJsonRelativePath } else { $null } $commandPath = if (-not [string]::IsNullOrWhiteSpace($commandFileName)) { Join-Path $RuntimeHome $commandFileName } else { $null } $packageJsonPath = if (-not [string]::IsNullOrWhiteSpace($packageJsonRelativePath)) { Join-Path $RuntimeHome $packageJsonRelativePath } else { $null } $packageVersion = $null $reportedVersion = $null $exists = (Test-Path -LiteralPath $RuntimeHome) $hasRequiredFiles = $false $versionsAligned = $false $failureReason = $null if (-not $exists) { $failureReason = 'RuntimeHomeMissing' } elseif ([string]::IsNullOrWhiteSpace($commandPath) -or [string]::IsNullOrWhiteSpace($packageJsonPath) -or -not (Test-Path -LiteralPath $commandPath) -or -not (Test-Path -LiteralPath $packageJsonPath)) { $failureReason = 'RequiredFilesMissing' } else { $hasRequiredFiles = $true try { $packageDocument = Get-Content -LiteralPath $packageJsonPath -Raw -ErrorAction Stop | ConvertFrom-Json $packageVersion = ConvertTo-ManifestedSemanticVersionText -VersionText ([string]$packageDocument.version) } catch { $packageVersion = $null } try { $reportedVersion = (& $commandPath --version 2>$null | Select-Object -First 1) if ($reportedVersion) { $reportedVersion = ConvertTo-ManifestedSemanticVersionText -VersionText $reportedVersion.ToString().Trim() } } catch { $reportedVersion = $null } if (-not [string]::IsNullOrWhiteSpace($packageVersion) -and -not [string]::IsNullOrWhiteSpace($reportedVersion) -and $packageVersion -eq $reportedVersion) { $versionsAligned = $true } else { $failureReason = 'VersionMismatch' } } return [pscustomobject]@{ Exists = $exists HasRequiredFiles = $hasRequiredFiles VersionsAligned = $versionsAligned IsUsable = ($exists -and $hasRequiredFiles -and $versionsAligned) FailureReason = $failureReason RuntimeHome = $RuntimeHome CommandPath = $commandPath PackageJsonPath = $packageJsonPath PackageVersion = $packageVersion ReportedVersion = $reportedVersion } } function Get-ManifestedNpmCliFactsFromDefinition { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [pscustomobject]$Definition, [string]$LocalRoot = (Get-ManifestedLocalRoot) ) if ([System.Environment]::OSVersion.Platform -ne [System.PlatformID]::Win32NT) { return (New-ManifestedRuntimeFacts -RuntimeName $Definition.runtimeName -CommandName $Definition.commandName -RuntimeKind 'NpmCli' -LocalRoot $LocalRoot -Layout $null -PlatformSupported:$false -BlockedReason ('Only Windows hosts are supported by this ' + $Definition.runtimeName + ' bootstrap.')) } $factsBlock = Get-ManifestedDefinitionBlock -Definition $Definition -SectionName 'facts' -BlockName 'npmCli' $installBlock = Get-ManifestedDefinitionBlock -Definition $Definition -SectionName 'install' -BlockName 'npmGlobalPackage' $layout = Get-ManifestedLayout -LocalRoot $LocalRoot $toolsRoot = $layout.($installBlock.toolsRootLayoutProperty) $stagePrefix = if ($installBlock.PSObject.Properties.Match('stagePrefix').Count -gt 0) { $installBlock.stagePrefix } else { (($Definition.runtimeName -replace 'Runtime$', '')).ToLowerInvariant() } $partialPaths = @() $partialPaths += @(Get-ManifestedStageDirectories -Prefix $stagePrefix -Mode TemporaryShort -LegacyRootPaths @($toolsRoot) | Select-Object -ExpandProperty FullName) $entries = @() if (Test-Path -LiteralPath $toolsRoot) { $runtimeRoots = Get-ChildItem -LiteralPath $toolsRoot -Directory -ErrorAction SilentlyContinue | Where-Object { $_.Name -notlike ('_stage_' + $stagePrefix + '_*') } | Sort-Object -Descending -Property @{ Expression = { ConvertTo-ManifestedSemanticVersionObject -VersionText $_.Name } }, Name foreach ($runtimeRoot in $runtimeRoots) { $validation = Test-ManifestedNpmCliRuntimeHome -Definition $Definition -RuntimeHome $runtimeRoot.FullName $expectedVersion = ConvertTo-ManifestedSemanticVersionText -VersionText $runtimeRoot.Name $runtimeVersion = if ($validation.PackageVersion) { $validation.PackageVersion } else { $expectedVersion } $versionMatches = (-not $expectedVersion) -or (-not $validation.PackageVersion) -or ($expectedVersion -eq $validation.PackageVersion) $isUsable = ($validation.IsUsable -and $versionMatches) $entries += [pscustomobject]@{ Version = $runtimeVersion RuntimeHome = $runtimeRoot.FullName ExecutablePath = $validation.CommandPath PackageJsonPath = $validation.PackageJsonPath Validation = $validation VersionMatches = $versionMatches IsUsable = $isUsable Source = 'Managed' } } } $managedRuntime = $entries | Where-Object { $_.IsUsable } | Select-Object -First 1 $externalRuntime = $null if (-not $managedRuntime) { $candidatePaths = New-Object System.Collections.Generic.List[string] foreach ($commandName in @($Definition.environment.commandProjection.expectedCommands)) { $candidatePath = Get-ManifestedApplicationPath -CommandName $commandName -ExcludedRoots @($toolsRoot) if (-not [string]::IsNullOrWhiteSpace($candidatePath)) { $candidatePaths.Add($candidatePath) | Out-Null } if ($commandName -match '\.cmd$') { $alternateCommandName = [System.IO.Path]::GetFileNameWithoutExtension($commandName) if (-not [string]::IsNullOrWhiteSpace($alternateCommandName)) { $alternateCandidatePath = Get-ManifestedApplicationPath -CommandName $alternateCommandName -ExcludedRoots @($toolsRoot) if (-not [string]::IsNullOrWhiteSpace($alternateCandidatePath)) { $candidatePaths.Add($alternateCandidatePath) | Out-Null } } } } foreach ($candidatePath in @($candidatePaths | Select-Object -Unique)) { $resolvedCandidatePath = Get-ManifestedFullPath -Path $candidatePath if ([string]::IsNullOrWhiteSpace($resolvedCandidatePath) -or -not (Test-Path -LiteralPath $resolvedCandidatePath)) { continue } $runtimeHome = Split-Path -Parent $resolvedCandidatePath $validation = Test-ManifestedNpmCliRuntimeHome -Definition $Definition -RuntimeHome $runtimeHome if (-not $validation.IsUsable) { continue } $externalRuntime = [pscustomobject]@{ Version = $validation.PackageVersion RuntimeHome = $runtimeHome ExecutablePath = $validation.CommandPath PackageJsonPath = $validation.PackageJsonPath Validation = $validation IsUsable = $true Source = 'External' Discovery = 'Path' } break } } $currentRuntime = if ($managedRuntime) { $managedRuntime } else { $externalRuntime } $invalidRuntimeHomes = @($entries | Where-Object { -not $_.IsUsable } | Select-Object -ExpandProperty RuntimeHome) return (New-ManifestedRuntimeFacts -RuntimeName $Definition.runtimeName -CommandName $Definition.commandName -RuntimeKind 'NpmCli' -LocalRoot $layout.LocalRoot -Layout $layout -ManagedRuntime $managedRuntime -ExternalRuntime $externalRuntime -PartialPaths $partialPaths -InvalidPaths $invalidRuntimeHomes -Version $(if ($currentRuntime) { $currentRuntime.Version } else { $null }) -RuntimeHome $(if ($currentRuntime) { $currentRuntime.RuntimeHome } else { $null }) -RuntimeSource $(if ($managedRuntime) { 'Managed' } elseif ($externalRuntime) { 'External' } else { $null }) -ExecutablePath $(if ($currentRuntime) { $currentRuntime.ExecutablePath } else { $null }) -RuntimeValidation $(if ($currentRuntime) { $currentRuntime.Validation } else { $null }) -AdditionalProperties @{ PackageJsonPath = if ($currentRuntime) { $currentRuntime.PackageJsonPath } else { $null } InvalidRuntimeHomes = $invalidRuntimeHomes }) } |