Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 133 additions & 0 deletions Build/LocalLibraries.Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

$failures = New-Object System.Collections.ArrayList
$tempRoot = Join-Path ([System.IO.Path]::GetTempPath()) (
'FieldWorksLocalLibrariesTests_' + [System.Guid]::NewGuid().ToString('N'))

function Assert-True {
param([bool]$Condition, [string]$Message)
if (-not $Condition) {
[void]$script:failures.Add("FAIL: $Message")
}
}

function Write-PackageMetadata {
param([string]$VersionDirectory, [string]$Source)
New-Item -ItemType Directory -Path $VersionDirectory -Force | Out-Null
@{ version = 2; contentHash = 'test'; source = $Source } |
ConvertTo-Json | Set-Content -LiteralPath (
Join-Path $VersionDirectory '.nupkg.metadata') -Encoding UTF8
}

try {
$packagesDirectory = Join-Path $tempRoot 'packages'
$localRepository = Join-Path $tempRoot 'feed'
New-Item -ItemType Directory -Path $localRepository -Force | Out-Null

$localMachine = Join-Path $packagesDirectory 'sil.machine\3.9.2'
$publishedMachine = Join-Path $packagesDirectory 'sil.machine\3.9.3'
$unrelatedPackage = Join-Path $packagesDirectory 'example.package\1.0.0'
Write-PackageMetadata -VersionDirectory $localMachine -Source $localRepository
Write-PackageMetadata -VersionDirectory $publishedMachine `
-Source 'https://api.nuget.org/v3/index.json'
Write-PackageMetadata -VersionDirectory $unrelatedPackage -Source $localRepository

Set-Content -LiteralPath (Join-Path $localRepository 'SIL.Machine.3.9.2.nupkg') `
-Value 'local package'
Set-Content -LiteralPath (
Join-Path $localRepository 'SIL.Machine.Morphology.HermitCrab.3.9.2.snupkg') `
-Value 'local symbols'
Set-Content -LiteralPath (Join-Path $localRepository 'Example.Package.1.0.0.nupkg') `
-Value 'unrelated package'
$managedFeedPackages = @(
'SIL.Core.18.0.0.nupkg',
'SIL.LCModel.11.0.0.nupkg',
'SIL.Chorus.LibChorus.6.0.0.nupkg',
'L10NSharp.10.0.0.nupkg'
)
foreach ($packageName in $managedFeedPackages) {
Set-Content -LiteralPath (Join-Path $localRepository $packageName) `
-Value 'managed package'
}

Import-Module (Join-Path $PSScriptRoot 'LocalLibraries.psm1') -Force
$config = Get-FieldWorksLocalLibraryConfig
Assert-True ($config.Keys.Count -eq 5) 'The catalogue should contain five libraries.'
foreach ($library in @('palaso', 'lcm', 'chorus', 'machine', 'l10nsharp')) {
Assert-True $config.Contains($library) "The catalogue should contain $library."
}

Clear-FieldWorksLocalLibraries -PackagesDirectory $packagesDirectory `
-LocalRepository $localRepository

Assert-True (-not (Test-Path $localMachine)) `
'Cleanup should remove cache entries restored from a filesystem source.'
Assert-True (Test-Path $publishedMachine) `
'Cleanup should preserve cache entries restored from an HTTP source.'
Assert-True (Test-Path $unrelatedPackage) `
'Cleanup should preserve packages outside the managed library catalogue.'
Assert-True (-not (Test-Path (
Join-Path $localRepository 'SIL.Machine.3.9.2.nupkg'))) `
'Cleanup should remove managed packages from the local feed.'
Assert-True (-not (Test-Path (
Join-Path $localRepository 'SIL.Machine.Morphology.HermitCrab.3.9.2.snupkg'))) `
'Cleanup should remove managed symbol packages from the local feed.'
Assert-True (Test-Path (Join-Path $localRepository 'Example.Package.1.0.0.nupkg')) `
'Cleanup should preserve unrelated packages in the local feed.'
foreach ($packageName in $managedFeedPackages) {
Assert-True (-not (Test-Path (Join-Path $localRepository $packageName))) `
"Cleanup should remove $packageName."
}

Clear-FieldWorksLibraryPackageCache -PackagesDirectory $packagesDirectory `
-Libraries @('machine')
Assert-True (-not (Test-Path $publishedMachine)) `
'Selected packing should evict a published cache entry with the same version.'
Assert-True (Test-Path $unrelatedPackage) `
'Selected packing should preserve cache entries outside its package family.'

$managerText = Get-Content -LiteralPath (
Join-Path $PSScriptRoot 'Manage-LocalLibraries.ps1') -Raw
Assert-True ($managerText -match '\$VersionOutputPath') `
'Manage-LocalLibraries should accept a packed-version output path.'
Assert-True ($managerText -match 'Import-Module.+LocalLibraries\.psm1') `
'Manage-LocalLibraries should import the shared library catalogue.'
Assert-True ($managerText -match 'Clear-FieldWorksLocalLibraries') `
'Manage-LocalLibraries should use the shared cache cleanup.'
Assert-True ($managerText -match 'Clear-FieldWorksLibraryPackageCache') `
'Pack mode should evict selected package families before local restore.'
Assert-True ($managerText -match 'Packing local libraries is build-scoped') `
'Direct pack mode should direct callers to build.ps1.'
Assert-True ($managerText -notmatch 'dotnet nuget add source') `
'Manage-LocalLibraries should not persist a user-level NuGet source.'
Assert-True ($managerText -match 'RestoreAdditionalProjectSources=\$LocalRepo') `
'Local pack restores should receive the local feed for dependent libraries.'

$buildText = Get-Content -LiteralPath (Join-Path $PSScriptRoot '..\build.ps1') -Raw
Assert-True ($buildText -match '\[string\[\]\]\$LocalLibraries') `
'build.ps1 should accept a LocalLibraries array.'
Assert-True ($buildText -match 'Clear-FieldWorksLocalLibraries') `
'build.ps1 should clean unselected local libraries before restore.'
Assert-True ($buildText -match 'VersionOutputPath') `
'build.ps1 should consume non-persistent packed version output.'
Assert-True (($buildText -match 'LOCAL_NUGET_REPO') -and `
($buildText -match 'RestoreAdditionalProjectSources')) `
'build.ps1 should add the local feed to configured restore sources.'

[xml]$nugetConfig = Get-Content -LiteralPath (Join-Path $PSScriptRoot '..\nuget.config')
Assert-True ($null -ne $nugetConfig.SelectSingleNode('/configuration/packageSources/clear')) `
'nuget.config should clear inherited user-level package sources.'
}
finally {
if (Test-Path $tempRoot) {
Remove-Item -LiteralPath $tempRoot -Recurse -Force
}
}

if ($failures.Count -gt 0) {
$failures | ForEach-Object { Write-Error $_ }
exit 1
}

Write-Host 'Local library tests passed.' -ForegroundColor Green
175 changes: 175 additions & 0 deletions Build/LocalLibraries.psm1
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

$script:LibraryConfig = [ordered]@{
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'
}
l10nsharp = @{
VersionProperty = 'L10NSharpVersion'
PdbRelativeDir = 'output/Debug/net462'
CachePrefixes = @('l10nsharp')
EnvVar = 'L10NSHARP_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'
PackProjects = @(
'src/SIL.Machine/SIL.Machine.csproj',
'src/SIL.Machine.Morphology.HermitCrab/SIL.Machine.Morphology.HermitCrab.csproj'
)
}
}

function Test-ManagedPackageName {
param([string]$Name, [string[]]$Prefixes)
$normalizedName = $Name.ToLowerInvariant()
foreach ($prefix in $Prefixes) {
if ($normalizedName -eq $prefix -or $normalizedName.StartsWith("$prefix.")) {
return $true
}
}
return $false
}

function Test-FilesystemPackageSource {
param([string]$Source)
if ([string]::IsNullOrWhiteSpace($Source)) {
return $false
}
$uri = $null
if ([System.Uri]::TryCreate($Source, [System.UriKind]::Absolute, [ref]$uri)) {
return $uri.IsFile
}
return [System.IO.Path]::IsPathRooted($Source)
}

function Get-SelectedPrefixes {
param([string[]]$Libraries)
$selected = if ($Libraries -and $Libraries.Count -gt 0) {
$Libraries
}
else {
@($script:LibraryConfig.Keys)
}
$prefixes = foreach ($library in $selected) {
if (-not $script:LibraryConfig.Contains($library)) {
throw "Unknown local library '$library'."
}
$script:LibraryConfig[$library].CachePrefixes
}
return @($prefixes | Sort-Object -Unique)
}

<#
.SYNOPSIS
Removes every cached version for the selected local-library groups.
#>
function Clear-FieldWorksLibraryPackageCache {
param([string]$PackagesDirectory, [string[]]$Libraries)
if (-not (Test-Path -LiteralPath $PackagesDirectory)) {
return
}
$prefixes = Get-SelectedPrefixes -Libraries $Libraries
$packageDirectories = @(Get-ChildItem -LiteralPath $PackagesDirectory -Directory |
Where-Object { Test-ManagedPackageName -Name $_.Name -Prefixes $prefixes })
foreach ($packageDirectory in $packageDirectories) {
Remove-Item -LiteralPath $packageDirectory.FullName -Recurse -Force
}
if ($packageDirectories.Count -gt 0) {
Write-Host ("Cleared {0} package cache folders." -f $packageDirectories.Count) `
-ForegroundColor Yellow
}
}

<#
.SYNOPSIS
Returns the configuration for FieldWorks-supported local libraries.
#>
function Get-FieldWorksLocalLibraryConfig {
return $script:LibraryConfig
}

<#
.SYNOPSIS
Removes locally sourced cache entries and managed packages from a local feed.
#>
function Clear-FieldWorksLocalLibraries {
param(
[string]$PackagesDirectory,
[string]$LocalRepository,
[string[]]$Libraries
)

$prefixes = Get-SelectedPrefixes -Libraries $Libraries
$cacheRemovalCount = 0
$feedRemovalCount = 0

if (Test-Path -LiteralPath $PackagesDirectory) {
$packageDirectories = @(Get-ChildItem -LiteralPath $PackagesDirectory -Directory |
Where-Object { Test-ManagedPackageName -Name $_.Name -Prefixes $prefixes })
foreach ($packageDirectory in $packageDirectories) {
foreach ($versionDirectory in @(Get-ChildItem -LiteralPath $packageDirectory.FullName -Directory)) {
$metadataPath = Join-Path $versionDirectory.FullName '.nupkg.metadata'
if (-not (Test-Path -LiteralPath $metadataPath)) {
continue
}
try {
$metadata = Get-Content -LiteralPath $metadataPath -Raw | ConvertFrom-Json
}
catch {
Write-Warning "Could not read NuGet metadata at '$metadataPath'; preserving it."
continue
}
if (Test-FilesystemPackageSource -Source $metadata.source) {
Remove-Item -LiteralPath $versionDirectory.FullName -Recurse -Force
$cacheRemovalCount++
}
}
if (@(Get-ChildItem -LiteralPath $packageDirectory.FullName -Force).Count -eq 0) {
Remove-Item -LiteralPath $packageDirectory.FullName -Force
}
}
}

if ($LocalRepository -and (Test-Path -LiteralPath $LocalRepository)) {
$feedPackages = @(Get-ChildItem -LiteralPath $LocalRepository -File |
Where-Object {
$_.Extension -in @('.nupkg', '.snupkg') -and
(Test-ManagedPackageName -Name $_.BaseName -Prefixes $prefixes)
})
foreach ($feedPackage in $feedPackages) {
Remove-Item -LiteralPath $feedPackage.FullName -Force
$feedRemovalCount++
}
}

if ($cacheRemovalCount -gt 0 -or $feedRemovalCount -gt 0) {
Write-Host ("Cleared {0} local cache entries and {1} local feed packages." -f `
$cacheRemovalCount, $feedRemovalCount) -ForegroundColor Yellow
}
}

Export-ModuleMember -Function Get-FieldWorksLocalLibraryConfig,
Clear-FieldWorksLocalLibraries, Clear-FieldWorksLibraryPackageCache
Loading
Loading