-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBuild-Scripts.ps1
More file actions
167 lines (139 loc) · 5.83 KB
/
Copy pathBuild-Scripts.ps1
File metadata and controls
167 lines (139 loc) · 5.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
<#
.SYNOPSIS
Validates that shared PowerShell functions between LibreSpot.ps1 and the
WPF backend script remain in sync. Future: generates both scripts from
shared source fragments.
.DESCRIPTION
Extracts function bodies from both scripts and compares the 86+ shared
functions for content drift. Any mismatch is reported as an error,
preventing silent one-lane-only changes that cause feature or security
regressions.
Run this as part of CI to catch shared-function drift before release.
.EXAMPLE
pwsh -File Build-Scripts.ps1 -Validate
pwsh -File Build-Scripts.ps1 -Inventory
.NOTES
Part of the "Extract shared PowerShell core logic" roadmap item (Cycle 11).
The validation pass runs without modifying any files.
#>
[CmdletBinding()]
param(
[switch]$Validate,
[switch]$Inventory
)
$ErrorActionPreference = 'Stop'
$mainScript = Join-Path $PSScriptRoot 'LibreSpot.ps1'
$backendScript = Join-Path $PSScriptRoot 'src/LibreSpot.Desktop/Backend/LibreSpot.Backend.ps1'
if (-not (Test-Path -LiteralPath $mainScript)) {
throw "Cannot find LibreSpot.ps1 at $mainScript"
}
if (-not (Test-Path -LiteralPath $backendScript)) {
throw "Cannot find LibreSpot.Backend.ps1 at $backendScript"
}
function Get-FunctionNames {
param([string]$ScriptPath)
$content = Get-Content -Path $ScriptPath -Raw
$names = [regex]::Matches($content, '(?m)^\s*function\s+([A-Za-z0-9_-]+)') |
ForEach-Object { $_.Groups[1].Value } |
Sort-Object -Unique
return $names
}
function Get-FunctionBody {
param(
[string]$ScriptContent,
[string]$FunctionName
)
# Match a top-level function definition whose closing brace sits at column 0.
# Escape the function name so hyphens and other regex-significant characters
# are treated literally.
$escapedName = [regex]::Escape($FunctionName)
$pattern = "(?ms)^function\s+${escapedName}\s*\{.+?^\}"
$match = [regex]::Match($ScriptContent, $pattern)
if ($match.Success) {
return $match.Value
}
return $null
}
function ConvertTo-NormalizedFunctionBody {
param([string]$Body)
if (-not $Body) { return '' }
# Normalize whitespace for comparison:
# - Trim each line
# - Remove blank lines
# - Collapse multiple spaces
$lines = $Body -split "`r?`n" |
ForEach-Object { $_.Trim() } |
Where-Object { $_ -ne '' }
return ($lines -join "`n")
}
$mainContent = Get-Content -Path $mainScript -Raw
$backendContent = Get-Content -Path $backendScript -Raw
$mainFunctions = Get-FunctionNames -ScriptPath $mainScript
$backendFunctions = Get-FunctionNames -ScriptPath $backendScript
$sharedNames = $mainFunctions | Where-Object { $backendFunctions -contains $_ } | Sort-Object
$mainOnly = $mainFunctions | Where-Object { $backendFunctions -notcontains $_ } | Sort-Object
$backendOnly = $backendFunctions | Where-Object { $mainFunctions -notcontains $_ } | Sort-Object
if ($Inventory) {
Write-Host "`n=== SHARED FUNCTION INVENTORY ===" -ForegroundColor Cyan
Write-Host "Main script functions: $($mainFunctions.Count)"
Write-Host "Backend script functions: $($backendFunctions.Count)"
Write-Host "Shared functions: $($sharedNames.Count)"
Write-Host "Main-only functions: $($mainOnly.Count)"
Write-Host "Backend-only functions: $($backendOnly.Count)"
Write-Host "`n--- Shared ($($sharedNames.Count)) ---" -ForegroundColor Green
foreach ($fn in $sharedNames) { Write-Host " $fn" }
Write-Host "`n--- Main-only ($($mainOnly.Count)) ---" -ForegroundColor Yellow
foreach ($fn in $mainOnly) { Write-Host " $fn" }
Write-Host "`n--- Backend-only ($($backendOnly.Count)) ---" -ForegroundColor Yellow
foreach ($fn in $backendOnly) { Write-Host " $fn" }
Write-Host ""
exit 0
}
if ($Validate) {
Write-Host "Validating shared function sync between scripts..." -ForegroundColor Cyan
Write-Host " Main: $mainScript ($($mainFunctions.Count) functions)"
Write-Host " Backend: $backendScript ($($backendFunctions.Count) functions)"
Write-Host " Shared: $($sharedNames.Count) functions"
Write-Host ""
$drifted = @()
$missing = @()
foreach ($fn in $sharedNames) {
$mainBody = Get-FunctionBody -ScriptContent $mainContent -FunctionName $fn
$backendBody = Get-FunctionBody -ScriptContent $backendContent -FunctionName $fn
if (-not $mainBody) {
$missing += "${fn}: could not extract from main script"
continue
}
if (-not $backendBody) {
$missing += "${fn}: could not extract from backend script"
continue
}
$mainNorm = ConvertTo-NormalizedFunctionBody -Body $mainBody
$backendNorm = ConvertTo-NormalizedFunctionBody -Body $backendBody
if ($mainNorm -ne $backendNorm) {
$drifted += $fn
}
}
if ($missing.Count -gt 0) {
Write-Host "=== EXTRACTION FAILURES ===" -ForegroundColor Red
foreach ($m in $missing) { Write-Host " $m" -ForegroundColor Red }
Write-Host ""
}
if ($drifted.Count -gt 0) {
Write-Host "=== DRIFTED FUNCTIONS ($($drifted.Count)) ===" -ForegroundColor Red
foreach ($fn in $drifted) {
Write-Host " $fn" -ForegroundColor Red
}
Write-Host ""
Write-Host "These functions exist in both scripts but have different implementations." -ForegroundColor Red
Write-Host "Update both scripts in the same commit to keep them in sync." -ForegroundColor Red
Write-Host ""
exit 1
}
Write-Host "All $($sharedNames.Count) shared functions are in sync." -ForegroundColor Green
exit 0
}
# Default: show usage
Write-Host "Usage:"
Write-Host " pwsh -File Build-Scripts.ps1 -Validate # Check shared functions for drift"
Write-Host " pwsh -File Build-Scripts.ps1 -Inventory # List all functions and their locations"