Private/Set-DFRoleEnv.ps1
|
#Requires -Version 7.0 function Get-DFRoleEnvState { <# .SYNOPSIS Returns this session's record of role variables DotForge wrote and conflicts it warned about. .DESCRIPTION Kept in a session global, not a $script: variable, so Import-Module DotForge -Force doesn't forget which values DotForge itself wrote. Written maps variable -> the value DotForge last wrote: a current value that differs was set outside DotForge (profile, parent shell, system environment). Warned holds the conflicts already reported this session. .OUTPUTS System.Collections.Hashtable. @{ Written = @{}; Warned = @{} }. #> [CmdletBinding()] [OutputType([hashtable])] param() if ($global:DFRoleEnvState -isnot [hashtable]) { $global:DFRoleEnvState = @{ Written = @{}; Warned = @{} } } $global:DFRoleEnvState } function Set-DFRoleEnv { <# .SYNOPSIS Sets a role's reserved environment variable for the role's winner, without overriding the user's own choice. .DESCRIPTION Precedence, highest first: an explicit $DFConfig.Defaults choice (-Reason Defaults); then a value set outside DotForge; then an auto-picked winner (-Reason priority or sole). When a Defaults choice replaces a different outside value, warns with both settings, once per session for each conflict: the user's config contradicts itself. A value equal to -Value is left as is. Called only by core, from a role block's declarative env. What DotForge wrote is kept in Get-DFRoleEnvState. .PARAMETER Name The variable. .PARAMETER Value The winner's value (already expanded). .PARAMETER Role The role name, for the warning. .PARAMETER Winner The winning tool, for the warning. .PARAMETER Reason How the winner was chosen: Defaults, priority or sole. .OUTPUTS None. #> [CmdletBinding()] param( [Parameter(Mandatory)][string]$Name, [Parameter(Mandatory)][AllowEmptyString()][string]$Value, [Parameter(Mandatory)][string]$Role, [Parameter(Mandatory)][string]$Winner, [Parameter(Mandatory)][ValidateSet('Defaults', 'priority', 'sole')][string]$Reason ) $state = Get-DFRoleEnvState $current = [Environment]::GetEnvironmentVariable($Name, 'Process') if ($current -ceq $Value) { $state.Written[$Name] = $Value return } $setOutside = $current -and $state.Written[$Name] -cne $current if ($setOutside) { if ($Reason -ne 'Defaults') { Write-Verbose "DotForge: keeping $Name='$current' (set outside DotForge) over $Role winner $Winner." return } # Once per session: `. $PROFILE` re-runs the profile's own assignment, # and the same contradiction needs reporting only once. $conflict = "$Name|$current|$Winner" if (-not $state.Warned.ContainsKey($conflict)) { $state.Warned[$conflict] = $true Write-Warning ("DotForge: $Name was '$current' but `$DFConfig.Defaults.$Role is '$Winner'; using $Winner.`n" + ' Remove one of the two settings to silence this.') } } [Environment]::SetEnvironmentVariable($Name, $Value, 'Process') $state.Written[$Name] = $Value } |