Skip to content

Commit a88406d

Browse files
committed
🛠️ [fix] Update caching logic and improve localization tests
- 🔧 Modify the cache handling in `ColorScripts-Enhanced.GapFill1.Tests.ps1` to check for script content changes instead of just timestamps - 🔧 Ensure that metadata is updated correctly after script changes - 🔧 Add signature generation for cache entries in `ColorScripts-Enhanced.GapFill2.Tests.ps1` - 🧪 Introduce new tests in `ColorScripts-Enhanced.Localization.Tests.ps1` to validate localization initialization and resource loading - 🧪 Add tests in `ColorScripts-Enhanced.PrivateCoverage.Tests.ps1` to cover private utility functions for JSON and hashtable conversions - 🧪 Enhance existing tests in `ColorScripts-Enhanced.Tests.ps1` to ensure cache rebuild logic works as expected - 🔧 Update `Test-Coverage.ps1` to exclude specific scripts from coverage analysis and report exclusions Signed-off-by: Nick2bad4u <20943337+Nick2bad4u@users.noreply.github.com>
1 parent b20095f commit a88406d

28 files changed

Lines changed: 1332 additions & 92 deletions

ColorScripts-Enhanced/ColorScripts-Enhanced.psd1

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
#
44
# Generated by: Nick2bad4u
55
#
6-
# Generated on: 12/7/2025
6+
# Generated on: 12/8/2025
77
#
88

99
@{
1010
# Script module or binary module file associated with this manifest.
1111
RootModule = 'ColorScripts-Enhanced.psm1'
1212

1313
# Version number of this module.
14-
ModuleVersion = '2025.12.07.1845'
14+
ModuleVersion = '2025.12.08.1032'
1515

1616
# Supported PSEditions
1717
CompatiblePSEditions = @('Desktop', 'Core')
@@ -211,7 +211,7 @@ PERFECT FOR
211211

212212
# ReleaseNotes of this module
213213
ReleaseNotes = @'
214-
Version 2025.12.07.1845:
214+
Version 2025.12.08.1032:
215215
- Enhanced caching system with OS-wide cache in AppData
216216
- 6-19x performance improvement
217217
- Cache stored in centralized location

ColorScripts-Enhanced/Private/Build-ScriptCache.ps1

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ function Build-ScriptCache {
1414

1515
$scriptName = [System.IO.Path]::GetFileNameWithoutExtension($ScriptPath)
1616
$cacheFile = Join-Path $script:CacheDir "$scriptName.cache"
17+
Remove-CacheEntryMetadataFile -ScriptName $scriptName
1718

1819
$result = [pscustomobject]@{
1920
ScriptName = $scriptName
@@ -46,10 +47,23 @@ function Build-ScriptCache {
4647
$scriptLastWrite = Get-FileLastWriteTime -Path $ScriptPath
4748
Set-FileLastWriteTime -Path $cacheFile -Timestamp $scriptLastWrite
4849
}
50+
51+
$signature = Get-FileContentSignature -Path $ScriptPath -IncludeHash
52+
Write-CacheEntryMetadataFile -ScriptName $scriptName -Signature $signature -CacheFile $cacheFile
4953
$result.Success = $true
5054
}
5155
catch {
5256
$result.StdErr = $_.Exception.Message
57+
try {
58+
if (Test-Path -LiteralPath $cacheFile -PathType Leaf) {
59+
Remove-Item -LiteralPath $cacheFile -Force -ErrorAction Stop
60+
}
61+
}
62+
catch {
63+
Write-Verbose ("Failed to remove incomplete cache '{0}': {1}" -f $cacheFile, $_.Exception.Message)
64+
}
65+
66+
Remove-CacheEntryMetadataFile -ScriptName $scriptName
5367
}
5468
}
5569
elseif (-not $result.StdErr) {
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
if (-not $script:CacheEntryMetadataExtension) {
2+
$script:CacheEntryMetadataExtension = '.cacheinfo'
3+
}
4+
5+
if (-not $script:CacheEntryMetadataVersion -or $script:CacheEntryMetadataVersion -lt 1) {
6+
$script:CacheEntryMetadataVersion = 1
7+
}
8+
9+
function Get-CacheEntryMetadataPath {
10+
[CmdletBinding()]
11+
[OutputType([string])]
12+
param(
13+
[Parameter(Mandatory)]
14+
[object]$ScriptName,
15+
16+
[Parameter()]
17+
[string]$CacheRoot
18+
)
19+
20+
$root = if ($PSBoundParameters.ContainsKey('CacheRoot') -and $CacheRoot) { $CacheRoot } else { $script:CacheDir }
21+
if (-not $root) {
22+
return $null
23+
}
24+
25+
$scriptNameValue = if ($null -ne $ScriptName) { [string]$ScriptName } else { $null }
26+
$trimmed = if ($scriptNameValue) { $scriptNameValue.Trim() } else { $null }
27+
if ([string]::IsNullOrWhiteSpace($trimmed)) {
28+
return $null
29+
}
30+
31+
return Join-Path -Path $root -ChildPath ("{0}{1}" -f $trimmed, $script:CacheEntryMetadataExtension)
32+
}
33+
34+
function Remove-CacheEntryMetadataFile {
35+
[CmdletBinding()]
36+
param(
37+
[Parameter(Mandatory)]
38+
[object]$ScriptName,
39+
40+
[Parameter()]
41+
[string]$CacheRoot
42+
)
43+
44+
$metadataPath = Get-CacheEntryMetadataPath -ScriptName $ScriptName -CacheRoot $CacheRoot
45+
if (-not $metadataPath) {
46+
return
47+
}
48+
49+
if (-not (Test-Path -LiteralPath $metadataPath -PathType Leaf)) {
50+
return
51+
}
52+
53+
try {
54+
Remove-Item -LiteralPath $metadataPath -Force -ErrorAction Stop
55+
}
56+
catch {
57+
Write-Verbose ("Failed to remove cache metadata '{0}': {1}" -f $metadataPath, $_.Exception.Message)
58+
}
59+
}
60+
61+
function Write-CacheEntryMetadataFile {
62+
[CmdletBinding()]
63+
param(
64+
[Parameter(Mandatory)]
65+
[ValidateNotNullOrEmpty()]
66+
[string]$ScriptName,
67+
68+
[Parameter(Mandatory)]
69+
[ValidateNotNull()]
70+
[pscustomobject]$Signature,
71+
72+
[Parameter(Mandatory)]
73+
[ValidateNotNullOrEmpty()]
74+
[string]$CacheFile,
75+
76+
[Parameter()]
77+
[string]$CacheGeneratedUtc,
78+
79+
[Parameter()]
80+
[string]$ModuleVersionOverride
81+
)
82+
83+
if (-not $script:CacheDir) {
84+
return
85+
}
86+
87+
$metadataPath = Get-CacheEntryMetadataPath -ScriptName $ScriptName
88+
if (-not $metadataPath) {
89+
return
90+
}
91+
92+
$nowUtc = (Get-Date).ToUniversalTime()
93+
$generatedUtc = if ([string]::IsNullOrWhiteSpace($CacheGeneratedUtc)) { $nowUtc.ToString('o') } else { $CacheGeneratedUtc }
94+
95+
$moduleVersion = $ModuleVersionOverride
96+
if (-not $moduleVersion) {
97+
try {
98+
if ($ExecutionContext -and $ExecutionContext.SessionState -and $ExecutionContext.SessionState.Module) {
99+
$moduleVersion = $ExecutionContext.SessionState.Module.Version.ToString()
100+
}
101+
}
102+
catch {
103+
$moduleVersion = $null
104+
}
105+
}
106+
107+
$hashAlgorithm = if ($Signature.PSObject.Properties['HashAlgorithm'] -and $Signature.HashAlgorithm) {
108+
[string]$Signature.HashAlgorithm
109+
}
110+
elseif ($script:CacheEntryHashAlgorithm) {
111+
$script:CacheEntryHashAlgorithm
112+
}
113+
else {
114+
'SHA256'
115+
}
116+
117+
$metadataObject = [pscustomobject]@{
118+
Version = $script:CacheEntryMetadataVersion
119+
CacheFile = [System.IO.Path]::GetFileName($CacheFile)
120+
ModuleVersion = $moduleVersion
121+
CacheGeneratedUtc = $generatedUtc
122+
LastValidatedUtc = $nowUtc.ToString('o')
123+
ScriptLength = [long]$Signature.Length
124+
ScriptHash = if ($Signature.PSObject.Properties['Hash']) { $Signature.Hash } else { $null }
125+
ScriptHashAlgorithm = $hashAlgorithm
126+
ScriptLastWriteTimeUtc = if ($Signature.PSObject.Properties['LastWriteTimeUtc'] -and $Signature.LastWriteTimeUtc) { $Signature.LastWriteTimeUtc.ToString('o') } else { $null }
127+
}
128+
129+
$json = $metadataObject | ConvertTo-Json -Depth 5
130+
Invoke-FileWriteAllText -Path $metadataPath -Content $json -Encoding $script:Utf8NoBomEncoding
131+
}

ColorScripts-Enhanced/Private/Ensure-CacheFormatVersion.ps1

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,20 @@ function Update-CacheFormatVersion {
7070
Write-Verbose ("Cache purge enumeration failed: {0}" -f $_.Exception.Message)
7171
}
7272

73+
try {
74+
Get-ChildItem -LiteralPath $CacheDirectory -Filter ('*{0}' -f $script:CacheEntryMetadataExtension) -File -ErrorAction Stop | ForEach-Object {
75+
try {
76+
Remove-Item -LiteralPath $_.FullName -Force -ErrorAction Stop
77+
}
78+
catch {
79+
Write-Verbose ("Failed to remove cache metadata file '{0}': {1}" -f $_.FullName, $_.Exception.Message)
80+
}
81+
}
82+
}
83+
catch {
84+
Write-Verbose ("Cache metadata purge enumeration failed: {0}" -f $_.Exception.Message)
85+
}
86+
7387
$moduleVersion = $null
7488
try {
7589
if ($ExecutionContext.SessionState -and $ExecutionContext.SessionState.Module) {

0 commit comments

Comments
 (0)