Files
skills/scripts/build.ps1

89 lines
3.1 KiB
PowerShell

# Build .skill archives from skills/<name>/ into dist/<name>.skill
# Usage: build.ps1 [-Names <name1>,<name2>] [-Prune]
# no args = build all skills/* into dist/<name>.skill
# -Prune = after build, remove dist/<name>.skill files whose <name>
# is NOT in skills/* (analogue of install.ps1 -Prune).
# Prune always scans the full dist/, ignores -Names filter.
#
# Uses .NET System.IO.Compression.ZipArchive directly to produce
# spec-compliant ZIPs with forward-slash entry names (Windows PowerShell 5.1's
# Compress-Archive writes backslashes, which break extraction on Linux/Mac).
[CmdletBinding()]
param(
[string[]]$Names = @(),
[switch]$Prune
)
$ErrorActionPreference = 'Stop'
$root = Split-Path -Parent $PSScriptRoot
$src = Join-Path $root 'skills'
$dist = Join-Path $root 'dist'
if (-not (Test-Path $dist)) { New-Item -Type Directory -Path $dist | Out-Null }
if ($Names.Count -eq 0) {
$Names = Get-ChildItem -Path $src -Directory | Sort-Object Name | Select-Object -ExpandProperty Name
}
Add-Type -AssemblyName System.IO.Compression
Add-Type -AssemblyName System.IO.Compression.FileSystem
function New-SkillArchive {
param(
[string]$SkillName,
[string]$SourceDir,
[string]$OutPath
)
if (Test-Path $OutPath) { Remove-Item $OutPath -Force }
$sourceFull = (Resolve-Path $SourceDir).ProviderPath.TrimEnd('\','/')
$archive = [System.IO.Compression.ZipFile]::Open(
$OutPath,
[System.IO.Compression.ZipArchiveMode]::Create
)
try {
$files = Get-ChildItem -Path $sourceFull -Recurse -File | Where-Object { $_.FullName -notmatch '__pycache__' }
foreach ($file in $files) {
$rel = $file.FullName.Substring($sourceFull.Length + 1) -replace '\\','/'
$entryName = "$SkillName/$rel"
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile(
$archive,
$file.FullName,
$entryName,
[System.IO.Compression.CompressionLevel]::Optimal
) | Out-Null
}
} finally {
$archive.Dispose()
}
}
foreach ($name in $Names) {
$srcDir = Join-Path $src $name
if (-not (Test-Path $srcDir -PathType Container)) {
Write-Warning "skip: $name (not found in skills/)"
continue
}
if (-not (Test-Path (Join-Path $srcDir 'SKILL.md'))) {
Write-Warning "skip: $name (missing SKILL.md)"
continue
}
$out = Join-Path $dist "$name.skill"
New-SkillArchive -SkillName $name -SourceDir $srcDir -OutPath $out
Write-Host "built: dist/$name.skill"
}
if ($Prune) {
$sourceNames = @(Get-ChildItem -Path $src -Directory | Select-Object -ExpandProperty Name)
$skillArchives = Get-ChildItem -Path $dist -Filter "*.skill" -File -ErrorAction SilentlyContinue
foreach ($archive in $skillArchives) {
$archiveName = [System.IO.Path]::GetFileNameWithoutExtension($archive.Name)
if ($sourceNames -notcontains $archiveName) {
Write-Host "pruning: $archiveName (not in skills/) -> $($archive.FullName)"
Remove-Item -Force $archive.FullName
}
}
}