src/Build-PackageData.ps1
function Build-PackageData { param( [Parameter(Mandatory)] $Bootstrapper, [Parameter(Mandatory)] [ValidateSet("Object","Install","File")] [string] $From, [Parameter(Mandatory)] $Options ) $Defaults = @{ "Name" = "Undefined" "Fullname" = "Undefined" "Version" = "Undefined" "Source" = "Undefined" "CachePath" = "Undefined" "NativePath" = "Undefined" "Offline" = $false "SkipDependencies" = $false "Stable" = $true "Unmanaged" = $false "Installed" = $false } $Options = If( @($Options).Count -gt 1 ){ $temp_options = @{} $Options | ForEach-Object { $iter_options = $_ $Defaults.Keys | ForEach-Object { $temp_options[ $_ ] = If( $iter_options[ $_ ] ){ $iter_options[ $_ ] } Elseif( $Defaults[ $_ ].ToString() -ne "Undefined") { $Defaults[ $_ ] } } } $temp_options } Else { $temp_options = @{} $Defaults.Keys | ForEach-Object { $temp_options[ $_ ] = If( $Options[ $_ ] ){ $Options[ $_ ] } Elseif( $Defaults[ $_ ].ToString() -ne "Undefined") { $Defaults[ $_ ] } } $temp_options } Resolve-CachedPackage -From $From -Options $Options -Bootstrapper $Bootstrapper $Out = @{} $default_keys = $Defaults.Keys | ForEach-Object { $_ } $default_keys | ForEach-Object { If( "$($Defaults[ $_ ])" -eq "Undefined" ){ $Out[ $_ ] = $Null } $Out[ $_ ] = $Options[ $_ ] } <# If Manifest and skipping logic gets implemented, the skipping logic: - may occur further up in the function - should not occur after the .Source check below #> If( -not( Test-Path $Out.Source ) ){ Write-Error "[Import-Package:Preparation] Unable to find package $( $Out.Name )" return } Write-Verbose "[Import-Package:Preparation] Reading package $( $Out.Name )$( If( $Out.Version ) { " $( $Out.Version )"})" $Out.XML = $Bootstrapper.ReadNuspec( $Out.Source ) Write-Verbose "[Import-Package:Preparation] Validating .nuspec for $( $Out.Name )..." & { $nuspec_id = $Out.XML.package.metadata.id.ToString() $nuspec_version = $Out.XML.package.metadata.version.ToString() $either_versions_available = $nuspec_version -or $Out.Version $both_versions_available = $nuspec_version -and $Out.Version $both_names_available = $nuspec_id -and $Out.Name $version_mismatch = & { # We only care if a version was specified in the nuspec If( -not [string]::IsNullOrWhiteSpace( $nuspec_version ) ){ # We only check for explicit mismatch, if a version was found on the prior PackageData If( -not [string]::IsNullOrWhiteSpace( $Out.Version ) ){ -not( $nuspec_version -like "$($Out.Version)*" ) } Else { # Otherwise, if no version was found from Resolve-CachedPackage, we return true $true } } } $names_mismatch = $nuspec_id -ne $Out.Name If( $both_names_available -and $either_versions_available ){ If( $version_mismatch ){ If( $Out.Unmanaged ){ $Out.Version = $nuspec_version } Elseif( $both_versions_available ) { Throw "[Import-Package:Preparation] Version mismatch for $( $Out.Name )" return } } If( $names_mismatch ){ If( $Out.Unmanaged ){ Write-Warning "[Import-Package:Preparation] Package $( $Out.Name ).nupkg has a nuspec with the name $nuspec_id. Changing name..." $Out.Name = $nuspec_id } Else { Throw "[Import-Package:Preparation] Package $( $Out.Name ).nupkg has a .nuspec with the invalid ID $nuspec_id." return } } } } Write-Verbose "[Import-Package:Preparation] Checking for OS-specific files" If( Test-Path "$(Split-Path $Out.Source )\runtimes" ){ $available_rids = Get-ChildItem "$(Split-Path $Out.Source )\runtimes" -Directory | Select-Object -ExpandProperty Name $Out.RIDs = $available_rids $rid = $Bootstrapper.graphs | ForEach-Object { <# A big problem with selecting a package RID is that there maybe: - multiple RID graphs - multiple RIDs on each graph - multiple RIDs in the nupkg (we will call these available_rids) The earlier an RID occurs on a RID graph, the more representative it is of the host operating system - for example, for a Windows 10 x64 graph: - "win10-x64" will typically be the first element - "win", "any", and "base" will be at the end of the graph To determine which available_rid is correct, we need to check how early on the graphs they are. To do that, we iterate over each graph, and record the index of each available_rid as they occur on said graph: #> $index_table = @{} $graph = $_ $available_rids | ForEach-Object { $i = $graph.IndexOf( $_ ) If( $i -ne -1 ){ # If they don't exist on the graph, we don't record them $index_table[ $_ ] = $i } } # for each available_rid that was found on the graph, # we return the one (as a key(rid)-value(index) pair) with the lowest index: $index_table.GetEnumerator() | Sort-Object -Property Value | Select-Object -First 1 # this will return null, if it wasn't found on the current graph } | Sort-Object -Property Value | Select-Object -First 1 # then we return the lowest kv-pair for all graphs If( Test-Path "$(Split-Path $Out.Source)\runtimes\$( $rid.Key )" ){ Write-Verbose "[Import-Package:Preparation] Found $( $Out.Name ) runtime files for this platform ($( $rid.Key ))." $Out.RID = $rid.Key Write-Verbose "[Import-Package:Preparation] Checking the OS-specific files for framework-specific files..." Try{ $rid_libs = Get-ChildItem "$(Split-Path $Out.Source )\runtimes\$( $rid.Key )\lib" -Directory -ErrorAction Stop | Select-Object -ExpandProperty Name $Out.RID_Frameworks = $rid_libs } Catch {} } } Write-Verbose "[Import-Package:Preparation] Checking OS-agnostic framework-specific files..." Try{ $Out.Frameworks = Get-ChildItem "$( Split-Path $Out.Source )\lib" -Directory -ErrorAction Stop | Select-Object -ExpandProperty Name } Catch {} Write-Verbose "[Import-Package:Preparation] Reading dependencies..." $out_dependencies = @{} Try { $out_dependencies.Agnostic = $Bootstrapper.ParseVersOnDeps( $Out.XML.package.metadata.dependencies.dependency ) } Catch {} Try{ $out_dependencies.ByFramework = & { $by_framework = @{} $Out.XML.package.metadata.dependencies.group | ForEach-Object { $group = $_ $by_framework[ $group.TargetFramework.ToString() ] = $Bootstrapper.ParseVersOnDeps( $group.dependency ) } $by_framework } } Catch {} If( $out_dependencies.Keys.Count ){ $Out.Dependencies = $out_dependencies } <# Output Object Keys: - NativePath - Unmanaged - Offline - Name - Version - Source - XML # the nuspec as parsed XML - RIDs (if applicable) # Available RIDS in package - RID (if applicable) # The RID best-suiting the OS. This is set here, because it can't be selected by the user - RID_Frameworks (if applicable) # Any framework folders for the above RID - Frameworks # Platform agnostic framework folders - Dependencies - Agnostic - ByFramework #> If(@( $PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent, ($VerbosePreference -ne 'SilentlyContinue') ) -contains $true ){ Write-Host Write-Verbose "[Import-Package:Preparation] Parsed data for package $( $Out.Name ):" $Out.GetEnumerator() | Sort-Object @{Expression={$_.Name}; Ascending=$true} | Sort-Object { $type = If( -not [string]::IsNullOrWhiteSpace( $_.Value ) ){ $_.Value.GetType().ToString() } # Assign a sort order based on type switch ($type) { 'System.Management.Automation.SwitchParameter' { return 3 } 'System.Boolean' { return 2 } default { return 1 } } } | ForEach-Object { If( -not [string]::IsNullOrEmpty( $_.Value ) -and (@( [System.Management.Automation.SwitchParameter], [bool] ) -contains $_.Value.GetType()) ){ If( $_.Value ){ Write-Host "-" $_.Key ":" "$($_.Value)" -ForegroundColor Green } Else { Write-Host "-" $_.Key ":" "$($_.Value)" -ForegroundColor Red } } Elseif( $_.Value ) { Write-Host "-" $_.Key ":" "$($_.Value)" } Else { Write-Host "-" $_.Key ":" "$($_.Value)" -ForegroundColor Red } } Write-Host } $Out } |