Files
ARCADIA-Studio/scripts/package-common.ps1
T

77 lines
4.9 KiB
PowerShell

#Requires -Version 5.1
# Shared prebuilt-artifact packaging helpers. No builds or downloads.
function Assert-PackageOrdinaryFile([string]$Path) {
$item = Get-Item -LiteralPath $Path
if ($item.PSIsContainer) { throw "Package input is a directory: $Path" }
$current = $item
while ($null -ne $current) {
if (($current.Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0) { throw "Package input has a symlink/reparse ancestor: $($current.FullName)" }
$current = if ($current -is [IO.FileInfo]) { $current.Directory } else { $current.Parent }
}
}
function Invoke-PackageHelper([string]$Python, [string[]]$Arguments) {
$raw = @(& $Python (Join-Path $PSScriptRoot 'package-artifacts.py') @Arguments)
if ($LASTEXITCODE -ne 0) { throw 'Package artifact preflight/verification failed.' }
if ($raw.Count) { return (($raw -join "`n") | ConvertFrom-Json) }
}
function Get-PackageDocumentation([string]$Repository, [string]$Platform, [string]$Python) {
$result = Invoke-PackageHelper $Python @('docs', '--repository', $Repository, '--platform', $Platform)
$inputs = [ordered]@{}
foreach ($entry in $result.files) { $inputs[$entry.path] = $entry.source }
return $inputs
}
function Read-PackageBuildEvidence([string]$Path, [string]$Target, $BinaryHashes) {
if (-not $Path) { return $null }
$evidence = Get-Content -LiteralPath $Path -Raw | ConvertFrom-Json
foreach ($field in @('source_identity', 'profile', 'compiler', 'target', 'binary_sha256')) {
if (-not $evidence.PSObject.Properties[$field]) { throw "Build evidence missing $field" }
}
if ($evidence.target -ne $Target) { throw 'Build evidence target differs from requested package target.' }
foreach ($field in @('source_identity', 'profile', 'compiler')) {
if ($evidence.$field -isnot [string] -or [string]::IsNullOrWhiteSpace($evidence.$field)) { throw "Build evidence $field must be explicit nonempty text." }
}
foreach ($name in $BinaryHashes.Keys) {
if (-not $evidence.binary_sha256.PSObject.Properties[$name] -or $evidence.binary_sha256.$name -cne $BinaryHashes[$name]) { throw "Build evidence binary hash mismatch: $name" }
}
return [ordered]@{ assertion = 'Caller-supplied build evidence; target and binary hashes checked, source/compiler/profile statements not inferred or independently proven by packaging.'; evidence = $evidence }
}
function Write-PackageNotices([string]$Stage, $Notices) {
$encoding = New-Object Text.UTF8Encoding($false)
[IO.File]::WriteAllText((Join-Path $Stage 'dependency-notices.json'), ($Notices.Inventory | ConvertTo-Json -Depth 18) + "`n", $encoding)
$index = @('Third-party notice inventory', '', 'Exact versions, license expressions, source hashes and notice paths: dependency-notices.json', 'License texts and embedded-asset notices: licenses/', 'Rust distribution notices: licenses/rust/', 'Collection does not establish binary/source equivalence or a universal license audit.', '')
foreach ($package in $Notices.Inventory.packages) { $index += "$($package.name) $($package.version) -- $($package.license) -- licenses/dependencies/$($package.name)-$($package.version)/" }
[IO.File]::WriteAllText((Join-Path $Stage 'THIRD-PARTY-NOTICES.txt'), ($index -join "`n") + "`n", $encoding)
}
function Copy-PackageInputs([string]$Stage, $Inputs, $InspectedHashes) {
$hashes = [ordered]@{}
foreach ($name in $Inputs.Keys) {
Assert-PackageOrdinaryFile $Inputs[$name]
$source = Get-Item -LiteralPath $Inputs[$name]
if ($source.PSIsContainer -or ($source.Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0) { throw "Package input must be an ordinary file: $name" }
$destination = Join-Path $Stage $name
[void][IO.Directory]::CreateDirectory([IO.Path]::GetDirectoryName($destination))
$before = (Get-FileHash -LiteralPath $source.FullName -Algorithm SHA256).Hash.ToLowerInvariant()
if ($InspectedHashes.ContainsKey($name) -and $InspectedHashes[$name] -ne $before) { throw "Input changed after inspection: $name" }
[IO.File]::Copy($source.FullName, $destination, $false)
if ((Get-FileHash -LiteralPath $destination -Algorithm SHA256).Hash.ToLowerInvariant() -ne $before) { throw "Input changed during staging: $name" }
$hashes[$name] = $before
}
return $hashes
}
function Write-PackageChecksums([string]$Stage) {
$encoding = New-Object Text.UTF8Encoding($false)
$lines = New-Object 'Collections.Generic.List[string]'
foreach ($file in Get-ChildItem -LiteralPath $Stage -Recurse -File | Sort-Object FullName) {
$relative = $file.FullName.Substring($Stage.Length + 1).Replace('\', '/')
if ($relative -eq 'SHA256SUMS.txt') { throw 'Package checksum manifest already exists.' }
$lines.Add((Get-FileHash -LiteralPath $file.FullName -Algorithm SHA256).Hash.ToLowerInvariant() + ' ' + $relative)
}
[IO.File]::WriteAllText((Join-Path $Stage 'SHA256SUMS.txt'), ($lines -join "`n") + "`n", $encoding)
}