Netscoot.Core/Private/PowerShellScripts.ps1
|
function Find-PowerShellFiles { # .ps1/.psm1 beneath a root. [CmdletBinding()] param([Parameter(Mandatory)][string]$Root) Get-ChildItem -LiteralPath $Root -Recurse -File -ErrorAction SilentlyContinue | Where-Object { $_.Extension -in '.ps1', '.psm1' -and $_.FullName -notmatch '[\\/]\.git[\\/]' } } function Get-PowerShellScriptReferences { # Dot-source (`. path`) and call (`& path`) invocations of a .ps1 in a script, via the # PowerShell AST (reliable across editions). Resolves literal paths and the $PSScriptRoot # token (= the script's own dir); other variables/expressions are flagged Unresolved. [CmdletBinding()] param([Parameter(Mandatory)][string]$File) $full = Resolve-FullPath $File $dir = Split-Path -Parent $full $tokens = $null; $errs = $null $ast = [System.Management.Automation.Language.Parser]::ParseFile($full, [ref]$tokens, [ref]$errs) $out = @() $cmds = $ast.FindAll({ param($n) $n -is [System.Management.Automation.Language.CommandAst] }, $true) foreach ($c in $cmds) { $op = $c.InvocationOperator.ToString() if ($op -ne 'Dot' -and $op -ne 'Ampersand') { continue } if ($c.CommandElements.Count -lt 1) { continue } $first = $c.CommandElements[0] $raw = $null if ($first -is [System.Management.Automation.Language.StringConstantExpressionAst]) { $raw = $first.Value } elseif ($first -is [System.Management.Automation.Language.ExpandableStringExpressionAst]) { $raw = $first.Value } else { continue } if ([string]::IsNullOrWhiteSpace($raw) -or $raw -notmatch '\.ps1$') { continue } $expanded = $raw -replace '\$PSScriptRoot', $dir if ($expanded -match '\$') { $out += [pscustomobject]@{ Raw = $raw; Abs = $null; Unresolved = $true }; continue } # Normalize Windows-style '\' separators to the platform's so a repository authored on Windows # still resolves on Unix (where '\' is a literal path character, not a separator). $expanded = $expanded.Replace('\', [System.IO.Path]::DirectorySeparatorChar) $abs = if ([System.IO.Path]::IsPathRooted($expanded)) { [System.IO.Path]::GetFullPath($expanded) } else { [System.IO.Path]::GetFullPath((Join-Path $dir $expanded)) } $out += [pscustomobject]@{ Raw = $raw; Abs = $abs; Unresolved = $false } } return $out } function Get-NewScriptRaw { # New raw reference text from $RefDir to $TargetAbs, preserving the original style: # $PSScriptRoot-prefixed, or a leading .\ for current-dir-relative dot-sourcing. [CmdletBinding()] param( [Parameter(Mandatory)][string]$RefDir, [Parameter(Mandatory)][string]$TargetAbs, [Parameter(Mandatory)][AllowEmptyString()][string]$OldRaw ) $rel = Get-RelativePathSafe -From $RefDir -To $TargetAbs # platform separator $sep = [System.IO.Path]::DirectorySeparatorChar if ($OldRaw -match '^\$PSScriptRoot') { return '$PSScriptRoot' + $sep + $rel } if ($rel -notmatch '^\.\.?[\\/]') { return '.' + $sep + $rel } # ensure dot-source finds a local path return $rel } |