Private/Invoke-DFToolCompanion.ps1
|
#Requires -Version 7.0 function Invoke-DFToolCompanion { <# .SYNOPSIS Dot-sources a tool's companion Tools/<name>.ps1 (if present) and its one-time Tools/<name>.setup.ps1 (if present, not yet run, and not skipped), setting $DFCurrentTool around each. .DESCRIPTION The regular companion runs every Register-DFTool call. The setup companion runs at most once ever per tool -- see docs/superpowers/specs/2026-09-04-tool-setup-lifecycle-design.md -- and is responsible for calling Complete-DFToolSetup itself on success; a thrown error here is caught and warned so the next Register-DFTool call retries it. Dot-sourcing runs the companion directly in this function's own scope (not a child scope), so $DFCurrentTool set here immediately before each dot-source is what the companion sees -- the sidecar contract only requires "set immediately before, cleared immediately after," not that it happen inside Register-DFTool specifically. Extracted verbatim from Register-DFTool's per-tool loop -- no behavior change from the prior inline version. .PARAMETER Tool The tool record whose companion(s) to run. .PARAMETER ToolsPath The resolved Tools/ directory to look for companions in. .PARAMETER SkipSetup Tool names ($DFConfig['SkipSetup']) whose one-time setup companion must never run. .OUTPUTS None #> # $DFCurrentTool is set before dot-sourcing companions so sidecars can # read it. PSScriptAnalyzer can't see the companion scope, so suppress # the false positive. [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'DFCurrentTool')] [CmdletBinding()] param( [Parameter(Mandatory)] [PSCustomObject]$Tool, [Parameter(Mandatory)] [string]$ToolsPath, [string[]]$SkipSetup = @() ) $companion = Join-Path $ToolsPath "$($Tool.name).ps1" if (Test-Path $companion -PathType Leaf) { $DFCurrentTool = $Tool . ($companion) Remove-Variable -Name DFCurrentTool -ErrorAction Ignore } $setupCompanion = Join-Path $ToolsPath "$($Tool.name).setup.ps1" if ((Test-Path $setupCompanion -PathType Leaf) -and $Tool.name -notin $SkipSetup -and -not (Get-DFToolSetupState).PSObject.Properties[$Tool.name]) { $DFCurrentTool = $Tool try { . ($setupCompanion) } catch { Write-Warning "DotForge: $($Tool.name) one-time setup failed: $($_.Exception.Message)" } Remove-Variable -Name DFCurrentTool -ErrorAction Ignore } } |