Lumi/companion/scripts/collect-nuget-notices.ps1
2026-07-24 14:44:27 +02:00

99 lines
4.8 KiB
PowerShell

param(
[Parameter(Mandatory = $true)][string]$RepoRoot,
[Parameter(Mandatory = $true)][string]$OutputRoot
)
$ErrorActionPreference = "Stop"
$repo = (Resolve-Path $RepoRoot).Path
$assetFiles = @(Get-ChildItem (Join-Path $repo "companion") -Filter project.assets.json -File -Recurse -ErrorAction SilentlyContinue |
Where-Object { $_.FullName -notmatch '[\\/]installer[\\/]output[\\/]' })
if ($assetFiles.Count -eq 0) { throw "No restored NuGet project.assets.json files were found after publish." }
Remove-Item $OutputRoot -Recurse -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $OutputRoot | Out-Null
function Get-ChildText([System.Xml.XmlNode]$Node, [string]$Name) {
if (!$Node) { return $null }
$child = $Node.SelectSingleNode("*[local-name()='$Name']")
if (!$child) { return $null }
return $child.InnerText.Trim()
}
$packages = @{}
foreach ($assetFile in $assetFiles) {
$assets = Get-Content $assetFile.FullName -Raw | ConvertFrom-Json
$packageFolders = @($assets.packageFolders.PSObject.Properties.Name)
foreach ($libraryProperty in $assets.libraries.PSObject.Properties) {
if ($libraryProperty.Value.type -ne "package") { continue }
$parts = $libraryProperty.Name -split '/', 2
if ($parts.Count -ne 2) { continue }
$id = $parts[0]
$version = $parts[1]
$key = "$($id.ToLowerInvariant())/$($version.ToLowerInvariant())"
if ($packages.ContainsKey($key)) { continue }
$packageRoot = $null
foreach ($folder in $packageFolders) {
$candidate = Join-Path $folder ($key -replace '/', [IO.Path]::DirectorySeparatorChar)
if (Test-Path $candidate) { $packageRoot = (Resolve-Path $candidate).Path; break }
}
if (!$packageRoot) { throw "Restored package files are missing for $id $version." }
$packages[$key] = [ordered]@{ Id = $id; Version = $version; Root = $packageRoot }
}
}
$inventory = [Collections.Generic.List[string]]::new()
$inventory.Add("LUMI COMPANION - EXACT NUGET PACKAGE LICENCE INVENTORY")
$inventory.Add("Generated: $([DateTime]::UtcNow.ToString('yyyy-MM-dd HH:mm:ss')) UTC")
$inventory.Add("")
$inventory.Add("This file is generated from the restored project.assets.json files used by the Companion build. Package-specific licence, notice, copying, and copyright files found in the restored packages are copied into the adjacent package directories.")
$inventory.Add("")
foreach ($package in @($packages.Values | Sort-Object Id, Version)) {
$safeName = ("$($package.Id)-$($package.Version)" -replace '[^A-Za-z0-9._-]', '_')
$packageOutput = Join-Path $OutputRoot $safeName
New-Item -ItemType Directory -Force -Path $packageOutput | Out-Null
$nuspec = Get-ChildItem $package.Root -Filter *.nuspec -File | Select-Object -First 1
$metadata = $null
if ($nuspec) {
[xml]$nuspecXml = Get-Content $nuspec.FullName -Raw
$metadata = $nuspecXml.SelectSingleNode("/*[local-name()='package']/*[local-name()='metadata']")
}
$licenseText = Get-ChildText $metadata "license"
if (!$licenseText) { $licenseText = Get-ChildText $metadata "licenseUrl" }
$authorsText = Get-ChildText $metadata "authors"
$copyrightText = Get-ChildText $metadata "copyright"
$projectUrlText = Get-ChildText $metadata "projectUrl"
$license = if ($licenseText) { $licenseText } else { "Not declared in package metadata" }
$authors = if ($authorsText) { $authorsText } else { "Not declared" }
$copyright = if ($copyrightText) { $copyrightText } else { "Not declared" }
$projectUrl = if ($projectUrlText) { $projectUrlText } else { "Not declared" }
$copied = [Collections.Generic.List[string]]::new()
$noticeFiles = @(Get-ChildItem $package.Root -File -Recurse -ErrorAction SilentlyContinue | Where-Object {
$_.Length -le 5MB -and $_.Name -match '^(license|licence|notice|third[-_. ]?party|thirdparty|copying|copyright)([._ -].*)?$'
})
foreach ($notice in $noticeFiles) {
$rootPrefix = $package.Root.TrimEnd([char[]]"\/")
$relative = $notice.FullName.Substring($rootPrefix.Length).TrimStart([char[]]"\/")
$targetName = ($relative -replace '[\\/:*?"<>|]', '__')
$target = Join-Path $packageOutput $targetName
Copy-Item $notice.FullName $target -Force
$copied.Add($targetName)
}
if ($copied.Count -eq 0) { Remove-Item $packageOutput -Force }
$inventory.Add("Package: $($package.Id) $($package.Version)")
$inventory.Add("Authors: $authors")
$inventory.Add("Copyright: $copyright")
$inventory.Add("Licence declaration: $license")
$inventory.Add("Project: $projectUrl")
$inventory.Add("Copied notice files: $(if ($copied.Count) { $copied -join ', ' } else { 'none found in restored package' })")
$inventory.Add("")
}
[IO.File]::WriteAllLines((Join-Path $OutputRoot "NuGet-LICENCE-INVENTORY.txt"), $inventory, [Text.UTF8Encoding]::new($false))
Write-Host "Collected legal metadata for $($packages.Count) restored NuGet packages."