Modules/businessdev.ALbuild.RuntimePackages/Private/Get-BcRuntimeDependencyChain.ps1
|
function Get-BcRuntimeDependencyChain { <# .SYNOPSIS Returns the transitive catalogue dependencies of one product, in install order. .DESCRIPTION The factory installs a product's dependency chain, produces the runtime package, and then tears the whole chain down again before the next product. That teardown is what keeps products from influencing each other's runtime package inside a shared container, and it is only possible if the chain is known explicitly - both to install it in the right order and to remove it in the reverse one. The chain is transitive: a product that depends on 365 business API also needs whatever the API depends on. It excludes the product itself, and lists each dependency once even when several products in the chain require it. Only catalogue members appear here. Dependencies resolved from a feed (Microsoft apps, third-party apps) are installed by Install-BcContainerDependency from the manifest and are not this function's concern. .PARAMETER Product The full catalogue (typically already ordered by Get-BcRuntimeProductOrder). .PARAMETER Name The product whose chain is wanted. .OUTPUTS System.Object[] - catalogue entries, dependencies first. #> [CmdletBinding()] [OutputType([object[]])] param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [object[]] $Product, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string] $Name ) $byName = [System.Collections.Specialized.OrderedDictionary]::new([System.StringComparer]::OrdinalIgnoreCase) foreach ($p in $Product) { $byName["$($p.Name)"] = $p } $chain = [System.Collections.Generic.List[object]]::new() $seen = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase) $walk = { param([string] $Current) $entry = $byName[$Current] if (-not $entry) { return } $dependsOn = @(Get-BcRuntimeProperty -InputObject $entry -Name 'DependsOn' -Default @()) foreach ($dep in $dependsOn) { $depName = "$dep" if ([string]::IsNullOrWhiteSpace($depName) -or -not $byName.Contains($depName)) { continue } # Guard against a cycle: without this the walk would recurse until the stack gives out. if (-not $seen.Add($depName)) { continue } & $walk $depName # dependencies of the dependency come first $chain.Add($byName[$depName]) } } [void]$seen.Add($Name) & $walk $Name return $chain.ToArray() } |