Repository navigation
Expand file tree
/
Copy pathpackage.ps1
More file actions
63 lines (63 loc) · 4.16 KB
/
Copy pathpackage.ps1
File metadata and controls
63 lines (63 loc) · 4.16 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
param([Parameter(Mandatory=$true)][ValidatePattern('^Kinetik(?:Stats|Calendar|Clock|Dock|Feeds|Focus|Hub|Notes|Screen|Weather)?$')][string]$App)
$ErrorActionPreference = 'Stop'
Set-Location $PSScriptRoot
Add-Type -AssemblyName System.IO.Compression.FileSystem
function Get-Sha256([string]$Path) {
$stream = [IO.File]::OpenRead($Path)
$sha = [Security.Cryptography.SHA256]::Create()
try { return [BitConverter]::ToString($sha.ComputeHash($stream)).Replace('-', '') }
finally { $stream.Dispose(); $sha.Dispose() }
}
$stage = Join-Path $PSScriptRoot ('.package-' + [Guid]::NewGuid().ToString('N'))
$candidate = Join-Path $PSScriptRoot ($App + '.candidate.zip')
$archive = Join-Path $PSScriptRoot ($App + '.zip')
try {
New-Item -ItemType Directory -Path $stage | Out-Null
foreach ($name in @(($App + '.exe'), 'README.md', 'LICENSE')) {
if (-not (Test-Path -LiteralPath $name -PathType Leaf)) { throw "Missing package input: $name" }
Copy-Item -LiteralPath $name -Destination $stage
}
if (Test-Path -LiteralPath 'RELEASE_NOTES_2026-10-16.md') { Copy-Item -LiteralPath 'RELEASE_NOTES_2026-10-16.md' -Destination $stage }
if ($App -in @('Kinetik', 'KinetikStats', 'KinetikScreen')) {
if (-not (Test-Path -LiteralPath 'lib\LibreHardwareMonitorLib.dll')) { throw 'Missing sensor library' }
New-Item -ItemType Directory -Path (Join-Path $stage 'lib') | Out-Null
Get-ChildItem -LiteralPath 'lib' -Filter '*.dll' | Copy-Item -Destination (Join-Path $stage 'lib')
}
$files = [ordered]@{}
Get-ChildItem -LiteralPath $stage -Recurse -File | Sort-Object FullName | ForEach-Object {
$relative = $_.FullName.Substring($stage.Length + 1).Replace('\', '/')
$files[$relative] = Get-Sha256 $_.FullName
}
$version = [Diagnostics.FileVersionInfo]::GetVersionInfo((Join-Path $stage ($App + '.exe'))).FileVersion
$manifest = [ordered]@{ app = $App; version = $version; files = $files }
$manifest | ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $stage 'release-manifest.json') -Encoding UTF8
$files.GetEnumerator() | ForEach-Object { $_.Value + ' ' + $_.Key } | Set-Content -LiteralPath (Join-Path $stage 'SHA256SUMS') -Encoding ASCII
if (Test-Path -LiteralPath $candidate) { Remove-Item -LiteralPath $candidate -Force }
[IO.Compression.ZipFile]::CreateFromDirectory($stage, $candidate)
$zip = [IO.Compression.ZipFile]::OpenRead($candidate)
try {
foreach ($file in $files.GetEnumerator()) {
$entry = @($zip.Entries | Where-Object { $_.FullName.Replace('\', '/') -eq $file.Key })
if ($entry.Count -ne 1) { throw "Missing or duplicate package entry: $($file.Key)" }
$stream = $entry[0].Open(); $hash = [Security.Cryptography.SHA256]::Create()
try { $actual = [BitConverter]::ToString($hash.ComputeHash($stream)).Replace('-', '') } finally { $stream.Dispose(); $hash.Dispose() }
if ($actual -ne $file.Value) { throw "Package checksum mismatch: $($file.Key)" }
}
} finally { $zip.Dispose() }
if (Test-Path -LiteralPath $archive) {
$old = Join-Path $PSScriptRoot '..\Old Versions\releases'
New-Item -ItemType Directory -Path $old -Force | Out-Null
Copy-Item -LiteralPath $archive -Destination (Join-Path $old ($App + '-' + [Guid]::NewGuid().ToString('N') + '.zip'))
}
Move-Item -LiteralPath $candidate -Destination $archive -Force
$zipHash = Get-Sha256 $archive
($zipHash + ' ' + $App + '.zip') | Set-Content -LiteralPath ($archive + '.sha256') -Encoding ASCII
Copy-Item -LiteralPath (Join-Path $stage 'release-manifest.json') -Destination 'release-manifest.json' -Force
Write-Host "Verified $archive ($version)"
Write-Host ('SHA-256 of `' + $App + '.exe`: `' + $files[($App + '.exe')] + '`')
} finally {
$rootPath = [IO.Path]::GetFullPath($PSScriptRoot).TrimEnd('\') + '\'
if (-not [IO.Path]::GetFullPath($stage).StartsWith($rootPath, [StringComparison]::OrdinalIgnoreCase)) { throw 'Unsafe staging path' }
if (Test-Path -LiteralPath $stage) { Remove-Item -LiteralPath $stage -Recurse -Force }
if (Test-Path -LiteralPath $candidate) { Remove-Item -LiteralPath $candidate -Force }
}