Support/Package/Schema/Eigenverft.Manifested.Sandbox.Package.Config.TemplatesLayout.ps1
|
<#
Eigenverft.Manifested.Sandbox.Package.Config — template resolution and depot/work-slot layout helpers. Loaded by Eigenverft.Manifested.Sandbox.Package.Config.ps1. #> function Resolve-PackageTemplateText { <# .SYNOPSIS Resolves simple Package template tokens in text. .DESCRIPTION Replaces package-aware tokens such as `{releaseTrack}`, `{version}`, and `{flavor}` with the current values from the resolved Package config and selected release. .PARAMETER Text The text that contains optional Package tokens. .PARAMETER PackageConfig The resolved Package config object. .PARAMETER Package The selected release object. .PARAMETER ExtraTokens Optional extra tokens to merge into the standard replacement map. .EXAMPLE Resolve-PackageTemplateText -Text '{releaseTrack}\{version}\{flavor}' -PackageConfig $config -Package $package #> [CmdletBinding()] param( [AllowNull()] [string]$Text, [AllowNull()] [psobject]$PackageConfig, [AllowNull()] [psobject]$Package, [hashtable]$ExtraTokens = @{} ) if ($null -eq $Text) { return $null } $tokens = Get-PackageTemplateTokenMap -PackageConfig $PackageConfig -Package $Package -ExtraTokens $ExtraTokens return Resolve-TemplateText -Text $Text -Tokens $tokens } function ConvertTo-PackageSafePathSegment { [CmdletBinding()] param( [AllowNull()] [string]$Value ) $segmentText = ([string]$Value).Trim() -replace '[\\/:\*\?"<>\|]', '-' if ([string]::IsNullOrWhiteSpace($segmentText)) { throw 'Package path layout produced an empty path segment.' } return $segmentText } function Get-PackageTemplateTokenMap { [CmdletBinding()] param( [AllowNull()] [psobject]$PackageConfig, [AllowNull()] [psobject]$Package, [hashtable]$ExtraTokens = @{}, [switch]$SanitizePathSegments ) $tokens = [ordered]@{} if ($PackageConfig) { $tokens['definitionId'] = $PackageConfig.DefinitionId $tokens['platform'] = $PackageConfig.Platform $tokens['architecture'] = $PackageConfig.Architecture $tokens['releaseTrack'] = $PackageConfig.ReleaseTrack if ($PackageConfig.PSObject.Properties['ApplicationRootDirectory']) { $tokens['applicationRootDirectory'] = $PackageConfig.ApplicationRootDirectory } if ($PackageConfig.PSObject.Properties['PreferredTargetInstallRootDirectory']) { $tokens['preferredTargetInstallDirectory'] = $PackageConfig.PreferredTargetInstallRootDirectory } if ($PackageConfig.PSObject.Properties['PackageFileStagingRootDirectory']) { $tokens['packageFileStagingDirectory'] = $PackageConfig.PackageFileStagingRootDirectory } if ($PackageConfig.PSObject.Properties['PackageInstallStageRootDirectory']) { $tokens['packageInstallStageDirectory'] = $PackageConfig.PackageInstallStageRootDirectory } if ($PackageConfig.PSObject.Properties['DefaultPackageDepotDirectory']) { $tokens['defaultPackageDepotDirectory'] = $PackageConfig.DefaultPackageDepotDirectory } } if ($Package) { $tokens['packageId'] = if ($Package.PSObject.Properties['id']) { [string]$Package.id } else { $null } $tokens['releaseId'] = if ($Package.PSObject.Properties['id']) { [string]$Package.id } else { $null } $tokens['releaseTrack'] = if ($Package.PSObject.Properties['releaseTrack']) { [string]$Package.releaseTrack } else { $tokens['releaseTrack'] } $tokens['version'] = if ($Package.PSObject.Properties['version']) { [string]$Package.version } else { $null } $tokens['flavor'] = if ($Package.PSObject.Properties['flavor']) { [string]$Package.flavor } else { $null } } foreach ($key in @($ExtraTokens.Keys)) { $tokens[$key] = $ExtraTokens[$key] } if ($SanitizePathSegments) { foreach ($key in @($tokens.Keys)) { if ($null -eq $tokens[$key]) { continue } $tokens[$key] = ConvertTo-PackageSafePathSegment -Value ([string]$tokens[$key]) } } return $tokens } function Resolve-PackageLayoutRelativeDirectory { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$Template, [Parameter(Mandatory = $true)] [psobject]$PackageConfig, [Parameter(Mandatory = $true)] [psobject]$Package, [hashtable]$ExtraTokens = @{} ) $tokens = Get-PackageTemplateTokenMap -PackageConfig $PackageConfig -Package $Package -ExtraTokens $ExtraTokens -SanitizePathSegments $resolvedPath = (Resolve-TemplateText -Text $Template -Tokens $tokens).Trim() -replace '/', '\' if ([string]::IsNullOrWhiteSpace($resolvedPath)) { throw 'Package layout template produced an empty relative path.' } if ([System.IO.Path]::IsPathRooted($resolvedPath)) { throw "Package layout template '$Template' produced rooted path '$resolvedPath'. Layout values must be relative." } $safeSegments = foreach ($segment in @($resolvedPath -split '\\')) { ConvertTo-PackageSafePathSegment -Value $segment } return (($safeSegments -join '\') -replace '/', '\') } function Get-PackagePackageDepotRelativeDirectory { <# .SYNOPSIS Builds the relative package-file directory for depot storage. .DESCRIPTION Derives the durable relative directory used below package depots from the configured depot layout template. .PARAMETER PackageConfig The resolved Package config object. .PARAMETER Package The selected release object. .EXAMPLE Get-PackagePackageDepotRelativeDirectory -PackageConfig $config -Package $package #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$PackageConfig, [Parameter(Mandatory = $true)] [psobject]$Package ) $template = if ($PackageConfig.PSObject.Properties['PackageDepotRelativePathTemplate'] -and -not [string]::IsNullOrWhiteSpace([string]$PackageConfig.PackageDepotRelativePathTemplate)) { [string]$PackageConfig.PackageDepotRelativePathTemplate } else { '{definitionId}/{releaseTrack}/{version}/{flavor}' } return Resolve-PackageLayoutRelativeDirectory -Template $template -PackageConfig $PackageConfig -Package $Package } function Get-PackagePackageWorkSlotDirectory { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$PackageConfig, [Parameter(Mandatory = $true)] [psobject]$Package ) $definitionId = [string]$PackageConfig.DefinitionId $releaseTrack = if ($Package.PSObject.Properties['releaseTrack']) { [string]$Package.releaseTrack } else { [string]$PackageConfig.ReleaseTrack } $version = if ($Package.PSObject.Properties['version']) { [string]$Package.version } else { $null } $flavor = if ($Package.PSObject.Properties['flavor']) { [string]$Package.flavor } else { $null } foreach ($requiredValue in @($definitionId, $releaseTrack, $version, $flavor)) { if ([string]::IsNullOrWhiteSpace($requiredValue)) { throw 'Package work slot derivation requires definition id, releaseTrack, version, and flavor.' } } $slotIdentity = '{0}|{1}|{2}|{3}' -f $definitionId, $releaseTrack, $version, $flavor $slotHash = Get-StableShortHash -InputText $slotIdentity -Length 8 $template = if ($PackageConfig.PSObject.Properties['PackageWorkSlotDirectoryTemplate'] -and -not [string]::IsNullOrWhiteSpace([string]$PackageConfig.PackageWorkSlotDirectoryTemplate)) { [string]$PackageConfig.PackageWorkSlotDirectoryTemplate } else { '{definitionId}-{slotHash}' } return Resolve-PackageLayoutRelativeDirectory -Template $template -PackageConfig $PackageConfig -Package $Package -ExtraTokens @{ slotHash = $slotHash } } |