Add portable Linux packaging and verify distribution notices

This commit is contained in:
2026-09-11 01:21:15 -07:00
committed by Codex
parent 65a1fef17c
commit 6d2b9619e3
24 changed files with 1374 additions and 141 deletions
+31 -5
View File
@@ -1,6 +1,8 @@
#Requires -Version 5.1
# Read-only dependency preflight. Does not build, download, or change a Cargo target.
function Get-WindowsNotices([string]$Repository, [string]$Target, [string]$NoticeManifest, [string]$LlvmMinGWRoot) {
function Get-ArcadiaNotices([string]$Repository, [string]$Target, [string]$NoticeManifest, [string]$LlvmMinGWRoot, [string[]]$RootPackages = @('oa-desktop', 'oa-server')) {
if ($RootPackages.Count -eq 0 -or @($RootPackages | Where-Object { $_ -notin @('oa-desktop', 'oa-server') }).Count -gt 0) { throw 'Notice roots must be oa-desktop and/or oa-server.' }
if ($LlvmMinGWRoot -and $Target -ne 'x86_64-pc-windows-gnullvm') { throw 'LLVM-MinGW runtime notices apply only to the gnullvm target.' }
function Hash-File([string]$Path) {
$stream = [IO.File]::OpenRead($Path)
$sha = [Security.Cryptography.SHA256]::Create()
@@ -10,7 +12,8 @@ function Get-WindowsNotices([string]$Repository, [string]$Target, [string]$Notic
function Under-Root([string]$Root, [string]$Relative) {
$base = [IO.Path]::GetFullPath($Root).TrimEnd('\', '/') + [IO.Path]::DirectorySeparatorChar
$path = [IO.Path]::GetFullPath((Join-Path $base $Relative))
if (-not $path.StartsWith($base, [StringComparison]::OrdinalIgnoreCase)) { throw "Notice path escapes source root: $Relative" }
$comparison = if ([IO.Path]::DirectorySeparatorChar -eq '/') { [StringComparison]::Ordinal } else { [StringComparison]::OrdinalIgnoreCase }
if (-not $path.StartsWith($base, $comparison)) { throw "Notice path escapes source root: $Relative" }
if (-not [IO.File]::Exists($path)) { throw "Required notice/source missing: $path" }
return $path
}
@@ -39,6 +42,17 @@ function Get-WindowsNotices([string]$Repository, [string]$Target, [string]$Notic
}
$lock = Under-Root $Repository 'Cargo.lock'
$lockHash = Hash-File $lock
# Shared compiler inputs live outside individual crate directories.
$workspaceInputs = [ordered]@{}
foreach ($relative in @('Cargo.toml', 'Cargo.lock', 'LICENSE', 'docs/openapi.json')) {
$workspaceInputs[$relative] = Hash-File (Under-Root $Repository $relative)
}
foreach ($file in @(Get-ChildItem -LiteralPath (Join-Path $Repository 'build') -Recurse -File | Sort-Object FullName)) {
if (($file.Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0) { throw 'Shared build input reparse point requires review.' }
$relative = $file.FullName.Substring([IO.Path]::GetFullPath($Repository).TrimEnd('\', '/').Length + 1).Replace('\', '/')
$workspaceInputs[$relative] = Hash-File $file.FullName
}
if (-not $workspaceInputs.Contains('build/windows_manifest.rs')) { throw 'Shared Windows build manifest input is missing.' }
$locked = @{}
foreach ($block in ([IO.File]::ReadAllText($lock) -split '(?m)^\[\[package\]\]\s*$')) {
$fields = @{}
@@ -53,7 +67,7 @@ function Get-WindowsNotices([string]$Repository, [string]$Target, [string]$Notic
foreach ($package in $metadata.packages) { $packages[$package.id] = $package }
foreach ($node in $metadata.resolve.nodes) { $nodes[$node.id] = $node }
$queue = New-Object 'Collections.Generic.Queue[string]'
foreach ($name in @('oa-desktop', 'oa-server')) {
foreach ($name in @($RootPackages | Sort-Object -Unique)) {
$roots = @($metadata.packages | Where-Object { $_.name -eq $name -and $metadata.workspace_members -contains $_.id })
if ($roots.Count -ne 1) { throw "Expected one workspace package: $name" }
$queue.Enqueue($roots[0].id)
@@ -100,8 +114,15 @@ function Get-WindowsNotices([string]$Repository, [string]$Target, [string]$Notic
# conservatively. Tests/examples/benches are excluded, never all font files by glob.
if ($file.Extension -eq '.rs' -and $relative -notmatch '^(tests|examples|benches)/') {
$text = [IO.File]::ReadAllText($file.FullName)
# Full-line comments, including rustdoc examples, are not compiled
# font embeds. Keep real code and feature-gated macros conservative.
$text = [regex]::Replace($text, '(?m)^[\t ]*//[^\r\n]*', '')
foreach ($match in [regex]::Matches($text, 'include_bytes!\s*\(\s*"([^"]+\.(?:ttf|otf|woff2?))"')) {
$font = Under-Root $root ([IO.Path]::GetFullPath((Join-Path $file.DirectoryName $match.Groups[1].Value)).Substring($root.Length + 1))
$fontPath = [IO.Path]::GetFullPath((Join-Path $file.DirectoryName $match.Groups[1].Value))
$fontRoot = [IO.Path]::GetFullPath($root).TrimEnd('\', '/') + [IO.Path]::DirectorySeparatorChar
$fontComparison = if ([IO.Path]::DirectorySeparatorChar -eq '/') { [StringComparison]::Ordinal } else { [StringComparison]::OrdinalIgnoreCase }
if (-not $fontPath.StartsWith($fontRoot, $fontComparison)) { throw "Embedded font path escapes crate source root: $key/$relative" }
$font = Under-Root $root $fontPath.Substring($fontRoot.Length)
[void]$fontReferences.Add($font.Substring($root.Length + 1).Replace('\', '/'))
}
}
@@ -156,5 +177,10 @@ function Get-WindowsNotices([string]$Repository, [string]$Target, [string]$Notic
}
}
if ($failures.Count -gt 0) { throw ("Notice preflight unresolved:`n - " + ($failures -join "`n - ")) }
return [pscustomobject]@{ Inputs = $inputs; Hashes = $hashes; Inventory = [ordered]@{ format_version = 1; target = $Target; cargo_lock_sha256 = $lockHash; scope = 'Target-filtered locked offline metadata; transitive normal/build edges from oa-desktop and oa-server. Workspace feature unification may include a conservative superset. No binary/source equivalence or universal license audit claimed.'; packages = @($records.ToArray()); rust = [ordered]@{ version = $rustVersion; notices = $rustNotices; target_libraries_sha256 = $rustLibraries }; runtime = $runtime } }
return [pscustomobject]@{ Inputs = $inputs; Hashes = $hashes; Inventory = [ordered]@{ format_version = 1; target = $Target; root_packages = @($RootPackages | Sort-Object -Unique); cargo_lock_sha256 = $lockHash; workspace_build_inputs_sha256 = $workspaceInputs; scope = 'Target-filtered locked offline metadata; transitive normal/build edges from the stated root packages. Workspace feature unification may include a conservative superset. No binary/source equivalence or universal license audit claimed.'; packages = @($records.ToArray()); rust = [ordered]@{ version = $rustVersion; notices = $rustNotices; target_libraries_sha256 = $rustLibraries }; runtime = $runtime } }
}
# Compatibility entry point for the reviewed Windows pipeline and its callers.
function Get-WindowsNotices([string]$Repository, [string]$Target, [string]$NoticeManifest, [string]$LlvmMinGWRoot) {
Get-ArcadiaNotices $Repository $Target $NoticeManifest $LlvmMinGWRoot
}