-
-
Notifications
You must be signed in to change notification settings - Fork 43
Expand file tree
/
Copy pathManage-LocalLibraries.ps1
More file actions
454 lines (377 loc) · 16.3 KB
/
Copy pathManage-LocalLibraries.ps1
File metadata and controls
454 lines (377 loc) · 16.3 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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
<#
.SYNOPSIS
Manages local SIL library versions for debugging in FieldWorks.
.DESCRIPTION
Two modes of operation:
Pack mode (one or more source paths provided):
Packs local checkouts of liblcm, libpalaso, chorus, and/or machine into the
local NuGet feed using each library's own version. Detects the version
from produced packages, updates SilVersions.props to match, copies
PDBs, and clears stale cached packages.
Multiple libraries can be packed in a single call. libpalaso is always
packed first (other libraries may depend on it).
SetVersion mode (-Library and -Version, no source paths):
Sets the version for a single library in SilVersions.props and clears
stale cached packages. Use this to revert to an upstream version or
switch to a specific version without packing.
To revert all libraries: git checkout Build/SilVersions.props
See Docs/architecture/local-library-debugging.md for the full workflow.
.PARAMETER Palaso
Switch: include libpalaso in the pack operation.
.PARAMETER PalasoPath
Path to a local libpalaso checkout. Overrides LIBPALASO_PATH env var.
Only used when -Palaso is specified.
.PARAMETER Lcm
Switch: include liblcm in the pack operation.
.PARAMETER LcmPath
Path to a local liblcm checkout. Overrides LIBLCM_PATH env var.
Only used when -Lcm is specified.
.PARAMETER Chorus
Switch: include chorus in the pack operation.
.PARAMETER ChorusPath
Path to a local chorus checkout. Overrides LIBCHORUS_PATH env var.
Only used when -Chorus is specified.
.PARAMETER Machine
Switch: include SIL.Machine in the pack operation.
.PARAMETER MachinePath
Path to a local machine checkout. Overrides SILMACHINE_PATH env var.
Only used when -Machine is specified.
.PARAMETER L10nSharp
Switch: include L10NSharp in the pack operation.
.PARAMETER L10nSharpPath
Path to a local L10NSharp checkout. Overrides L10NSHARP_PATH env var.
Only used when -L10nSharp is specified.
.PARAMETER Library
Which library to set a version for (SetVersion mode only):
lcm, palaso, chorus, machine, or l10nsharp.
.PARAMETER Version
Sets the version in SilVersions.props (SetVersion mode). Use to revert
to an upstream version. Not used in pack mode.
.EXAMPLE
.\Build\Manage-LocalLibraries.ps1 -Palaso -PalasoPath C:\Repos\libpalaso
Packs libpalaso, detects its version, and updates SilVersions.props.
.EXAMPLE
.\Build\Manage-LocalLibraries.ps1 -Palaso -Chorus -ChorusPath C:\Repos\chorus
Packs libpalaso (from env var) and then chorus from the given path.
.EXAMPLE
.\Build\Manage-LocalLibraries.ps1 -Library palaso -Version 17.0.0
Sets libpalaso version to 17.0.0 in SilVersions.props (e.g. to revert).
#>
[CmdletBinding()]
param(
[switch]$Palaso,
[string]$PalasoPath,
[switch]$Lcm,
[string]$LcmPath,
[switch]$Chorus,
[string]$ChorusPath,
[switch]$Machine,
[string]$MachinePath,
[switch]$L10nSharp,
[string]$L10nSharpPath,
[ValidateSet('palaso', 'lcm', 'chorus', 'machine', 'l10nsharp')]
[string]$Library,
[string]$Version
)
$ErrorActionPreference = "Stop"
# ---------------------------------------------------------------------------
# Library-specific configuration
# ---------------------------------------------------------------------------
$LibraryConfig = @{
palaso = @{
VersionProperty = 'SilLibPalasoVersion'
PdbRelativeDir = 'output/Debug/net462'
CachePrefixes = @(
'sil.core', 'sil.windows', 'sil.dblbundle', 'sil.writingsystems',
'sil.dictionary', 'sil.lift', 'sil.lexicon', 'sil.archiving',
'sil.media', 'sil.scripture', 'sil.testutilities'
)
EnvVar = 'LIBPALASO_PATH'
}
lcm = @{
VersionProperty = 'SilLcmVersion'
PdbRelativeDir = 'artifacts/Debug/net462'
CachePrefixes = @('sil.lcmodel')
EnvVar = 'LIBLCM_PATH'
}
chorus = @{
VersionProperty = 'SilChorusVersion'
PdbRelativeDir = 'output/Debug/net462'
CachePrefixes = @('sil.chorus')
EnvVar = 'LIBCHORUS_PATH'
}
machine = @{
VersionProperty = 'SilMachineVersion'
PdbRelativeDir = 'bin/Debug/netstandard2.0'
CachePrefixes = @('sil.machine')
EnvVar = 'SILMACHINE_PATH'
# Pack only the projects FieldWorks uses (avoids native CMake deps)
PackProjects = @(
'src/SIL.Machine/SIL.Machine.csproj',
'src/SIL.Machine.Morphology.HermitCrab/SIL.Machine.Morphology.HermitCrab.csproj'
)
}
l10nsharp = @{
VersionProperty = 'L10NSharpVersion'
PdbRelativeDir = 'output/Debug/net462'
CachePrefixes = @('l10nsharp')
EnvVar = 'L10NSHARP_PATH'
}
}
# Pack order: libpalaso first (other libraries may depend on it)
$PackOrder = @('palaso', 'l10nsharp', 'lcm', 'chorus', 'machine')
# ---------------------------------------------------------------------------
# Read SilVersions.props
# ---------------------------------------------------------------------------
$repoRoot = Split-Path $PSScriptRoot -Parent
$versionPropsPath = Join-Path $PSScriptRoot "SilVersions.props"
if (-not (Test-Path $versionPropsPath)) {
throw "SilVersions.props not found at $versionPropsPath"
}
[xml]$versionProps = Get-Content -LiteralPath $versionPropsPath
# ---------------------------------------------------------------------------
# Helper: get version node for a library
# ---------------------------------------------------------------------------
function Get-VersionNode {
param([string]$LibName)
$cfg = $LibraryConfig[$LibName]
$node = $versionProps.SelectSingleNode(
"//PropertyGroup[@Label='SIL Ecosystem Versions']/$($cfg.VersionProperty)")
if (-not $node) {
throw "Could not find <$($cfg.VersionProperty)> in SilVersions.props"
}
return $node
}
# ---------------------------------------------------------------------------
# Helper: update SilVersions.props and clear stale cached packages
# ---------------------------------------------------------------------------
function Update-VersionAndClearCache {
param([string]$LibName, [string]$NewVersion)
$cfg = $LibraryConfig[$LibName]
$node = Get-VersionNode $LibName
$node.InnerText = $NewVersion
# Save with XmlWriter to preserve tab indentation (XmlDocument.Save() converts tabs to spaces)
$writerSettings = New-Object System.Xml.XmlWriterSettings
$writerSettings.Indent = $true
$writerSettings.IndentChars = "`t"
$writerSettings.NewLineChars = "`r`n"
$writerSettings.Encoding = New-Object System.Text.UTF8Encoding($false) # UTF-8 without BOM
$writerSettings.OmitXmlDeclaration = -not $versionProps.FirstChild.NodeType.Equals([System.Xml.XmlNodeType]::XmlDeclaration)
$writer = [System.Xml.XmlWriter]::Create($versionPropsPath, $writerSettings)
try {
$versionProps.WriteTo($writer)
} finally {
$writer.Close()
}
Write-Host "Updated SilVersions.props ($($cfg.VersionProperty) = $NewVersion)" -ForegroundColor Yellow
$packagesDir = Join-Path $repoRoot "packages"
if (Test-Path $packagesDir) {
$patterns = $cfg.CachePrefixes | ForEach-Object { "$packagesDir/$_*" }
$stale = @(Get-ChildItem -Path $patterns -Directory -ErrorAction SilentlyContinue)
if ($stale.Count -gt 0) {
$stale | Remove-Item -Recurse -Force
Write-Host "Cleared $($stale.Count) stale package folder(s) from packages/." -ForegroundColor Yellow
}
}
}
# ---------------------------------------------------------------------------
# Helper: extract version from a .nupkg filename
# ---------------------------------------------------------------------------
# Split on '.', find the first segment starting with a digit — everything
# from there onward (minus .nupkg) is the version.
# E.g. SIL.Windows.Forms.Keyboarding.18.0.0-beta.nupkg → 18.0.0-beta
function Get-PackageVersion {
param([string]$FileName)
$base = $FileName -replace '\.nupkg$', ''
$segments = $base -split '\.'
for ($i = 0; $i -lt $segments.Count; $i++) {
if ($segments[$i] -match '^\d') {
return ($segments[$i..($segments.Count - 1)] -join '.')
}
}
return $null
}
# ---------------------------------------------------------------------------
# Helper: pack a single library
# ---------------------------------------------------------------------------
function Invoke-PackLibrary {
param([string]$LibName, [string]$SourceDir, [string]$LocalRepo)
$cfg = $LibraryConfig[$LibName]
$node = Get-VersionNode $LibName
Write-Host ""
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "Packing $LibName" -ForegroundColor Cyan
Write-Host " Source: $SourceDir" -ForegroundColor Cyan
Write-Host " Current: $($node.InnerText.Trim())" -ForegroundColor Cyan
Write-Host " Output: $LocalRepo" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
# Record timestamp before pack so we can find newly-produced packages
$packStart = Get-Date
Write-Host "Running dotnet pack..." -ForegroundColor Cyan
$commonPackArgs = @(
'-c', 'Debug'
"-p:IncludeSymbols=true"
"-p:SymbolPackageFormat=snupkg"
'--output', $LocalRepo
)
$projects = $cfg.PackProjects
if ($projects -and $projects.Count -gt 0) {
foreach ($proj in $projects) {
$projPath = Join-Path $SourceDir $proj
& dotnet pack $projPath @commonPackArgs
if ($LASTEXITCODE -ne 0) {
throw "dotnet pack failed for $LibName ($proj)."
}
}
}
else {
& dotnet pack $SourceDir @commonPackArgs
if ($LASTEXITCODE -ne 0) {
throw "dotnet pack failed for $LibName."
}
}
# Find .nupkg files created after pack started (exclude .snupkg and test pkgs)
$newPackages = @(
Get-ChildItem -Path $LocalRepo -Filter "*.nupkg" -File |
Where-Object { $_.LastWriteTime -ge $packStart -and $_.Extension -eq '.nupkg' -and $_.Name -notmatch 'tests' }
)
if ($newPackages.Count -eq 0) {
$currentVer = (Get-VersionNode $LibName).InnerText.Trim()
Write-Host ""
Write-Host "WARNING: No new .nupkg files were produced for $LibName." -ForegroundColor Yellow
Write-Host " The library version may not have changed since the last pack." -ForegroundColor Yellow
Write-Host " Current version in SilVersions.props: $currentVer" -ForegroundColor Yellow
Write-Host " Skipping version update for $LibName." -ForegroundColor Yellow
return
}
Write-Host "New packages found:" -ForegroundColor Gray
$newPackages | ForEach-Object { Write-Host " $($_.Name)" -ForegroundColor Gray }
$detectedVersions = @($newPackages | ForEach-Object { Get-PackageVersion $_.Name } |
Where-Object { $_ } | Sort-Object -Unique)
Write-Host "Detected version(s): $($detectedVersions -join ', ')" -ForegroundColor Gray
if ($detectedVersions.Count -eq 0) {
throw "Could not parse version from produced packages: $($newPackages.Name -join ', ')"
}
if ($detectedVersions.Count -gt 1) {
Write-Host "WARNING: Multiple versions detected in produced packages:" -ForegroundColor Red
$detectedVersions | ForEach-Object { Write-Host " $_" -ForegroundColor Red }
throw "Expected all packages to share one version. Clean $LocalRepo and retry."
}
$packVersion = $detectedVersions[0]
Write-Host ""
Write-Host "Pack complete ($($newPackages.Count) package(s), version $packVersion)." -ForegroundColor Green
# Update SilVersions.props and clear cache
Update-VersionAndClearCache -LibName $LibName -NewVersion $packVersion
Write-Host "To revert: git checkout Build/SilVersions.props" -ForegroundColor Yellow
# Copy PDB files to Output/Debug/ and Downloads/
$pdbSourceDir = Join-Path $SourceDir $cfg.PdbRelativeDir
if (Test-Path $pdbSourceDir) {
$outputDebugDir = Join-Path $repoRoot "Output/Debug"
$downloadsDir = Join-Path $repoRoot "Downloads"
foreach ($dir in @($outputDebugDir, $downloadsDir)) {
if (-not (Test-Path $dir)) {
New-Item -Path $dir -ItemType Directory -Force | Out-Null
}
}
$pdbFiles = @(Get-ChildItem -Path $pdbSourceDir -Filter "*.pdb" -File)
if ($pdbFiles.Count -gt 0) {
Write-Host "Copying $($pdbFiles.Count) PDB file(s) to Output/Debug/ and Downloads/..." -ForegroundColor Cyan
$pdbFiles | Copy-Item -Destination $outputDebugDir -Force
$pdbFiles | Copy-Item -Destination $downloadsDir -Force
}
else {
Write-Host "No PDB files found in $pdbSourceDir" -ForegroundColor Yellow
}
}
else {
Write-Host "PDB source directory not found: $pdbSourceDir (PDBs will only be in .snupkg)" -ForegroundColor Yellow
}
Write-Host ""
Write-Host "[OK] $LibName packed successfully." -ForegroundColor Green
}
# ===========================================================================
# Build the list of libraries to pack (in order)
# ===========================================================================
# Map switches and explicit paths to library names
$switchMap = @{
palaso = @{ Enabled = [bool]$Palaso; ExplicitPath = $PalasoPath }
lcm = @{ Enabled = [bool]$Lcm; ExplicitPath = $LcmPath }
chorus = @{ Enabled = [bool]$Chorus; ExplicitPath = $ChorusPath }
machine = @{ Enabled = [bool]$Machine; ExplicitPath = $MachinePath }
l10nsharp = @{ Enabled = [bool]$L10nSharp; ExplicitPath = $L10nSharpPath }
}
# Resolve source paths: explicit path > env var (only when switch is set)
$toPack = [ordered]@{}
foreach ($lib in $PackOrder) {
$sw = $switchMap[$lib]
if (-not $sw.Enabled) { continue }
$cfg = $LibraryConfig[$lib]
$path = $sw.ExplicitPath
if (-not $path) {
$path = [System.Environment]::GetEnvironmentVariable($cfg.EnvVar)
}
if (-not $path) {
throw "-$($lib) was specified but no path was provided and $($cfg.EnvVar) is not set."
}
if (-not (Test-Path $path)) {
throw "Source path for $lib does not exist: $path"
}
$toPack[$lib] = $path
}
# ===========================================================================
# Determine mode
# ===========================================================================
if ($toPack.Count -gt 0) {
# -----------------------------------------------------------------------
# Pack mode
# -----------------------------------------------------------------------
if ($Version) {
Write-Host "WARNING: -Version is ignored in pack mode (version is detected from produced packages)." -ForegroundColor Yellow
}
$localRepo = $env:LOCAL_NUGET_REPO
if (-not $localRepo) {
throw "The LOCAL_NUGET_REPO environment variable is not set. Set it to a folder path (e.g. C:\localnugetpackages)."
}
if (-not (Test-Path $localRepo)) {
Write-Host "Creating local NuGet repo folder: $localRepo" -ForegroundColor Yellow
New-Item -Path $localRepo -ItemType Directory -Force | Out-Null
}
# Ensure local NuGet source is registered (user-level config)
$sourceList = & dotnet nuget list source 2>&1
$normalizedRepo = [System.IO.Path]::GetFullPath($localRepo).TrimEnd('\', '/')
$alreadyRegistered = $sourceList | Where-Object {
$_.Trim() -replace '[\\/]$', '' -ieq $normalizedRepo
}
if (-not $alreadyRegistered) {
& dotnet nuget add source $localRepo --name local 2>&1 | Out-Null
Write-Host "Added local NuGet source: $localRepo" -ForegroundColor Yellow
}
Write-Host ""
Write-Host "Libraries to pack: $($toPack.Keys -join ', ')" -ForegroundColor Cyan
foreach ($lib in $toPack.Keys) {
Invoke-PackLibrary -LibName $lib -SourceDir $toPack[$lib] -LocalRepo $localRepo
}
Write-Host ""
Write-Host "========================================" -ForegroundColor Green
Write-Host "[OK] All libraries packed. Run .\build.ps1 to build." -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Green
}
elseif ($Library -and $Version) {
# -----------------------------------------------------------------------
# SetVersion mode
# -----------------------------------------------------------------------
$node = Get-VersionNode $Library
Write-Host ""
Write-Host "Manage-LocalLibrary (SetVersion)" -ForegroundColor Cyan
Write-Host " Library: $Library" -ForegroundColor Cyan
Write-Host " Current: $($node.InnerText.Trim())" -ForegroundColor Cyan
Write-Host " New: $Version" -ForegroundColor Cyan
Write-Host ""
Update-VersionAndClearCache -LibName $Library -NewVersion $Version
Write-Host ""
Write-Host "[OK] $Library version set to $Version" -ForegroundColor Green
Write-Host "Run .\build.ps1 to restore and build with the new version." -ForegroundColor Cyan
}
else {
throw "Nothing to do. Use -Palaso/-Lcm/-Chorus/-Machine/-L10nSharp switches to pack, or -Library and -Version to set a version.`nExamples:`n .\Build\Manage-LocalLibraries.ps1 -Palaso -PalasoPath C:\Repos\libpalaso`n .\Build\Manage-LocalLibraries.ps1 -Palaso -Chorus`n .\Build\Manage-LocalLibraries.ps1 -Machine -MachinePath C:\Repos\machine`n .\Build\Manage-LocalLibraries.ps1 -Library l10nsharp -Version 10.0.0`n .\Build\Manage-LocalLibraries.ps1 -Library palaso -Version 17.0.0"
}