158 lines
5.1 KiB
PowerShell
158 lines
5.1 KiB
PowerShell
# PowerShell equivalents for key .agents bash scripts
|
|
# These provide Windows-native alternatives for the most commonly used functions
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Common utility functions for Spec-Kit PowerShell scripts.
|
|
.DESCRIPTION
|
|
PowerShell equivalent of .agents/scripts/bash/common.sh
|
|
Provides repository root detection, branch identification, and feature path resolution.
|
|
#>
|
|
|
|
function Get-RepoRoot {
|
|
try {
|
|
$root = git rev-parse --show-toplevel 2>$null
|
|
if ($LASTEXITCODE -eq 0) { return $root.Trim() }
|
|
} catch {}
|
|
# Fallback: navigate up from script location
|
|
return (Resolve-Path "$PSScriptRoot\..\..\..").Path
|
|
}
|
|
|
|
function Get-CurrentBranch {
|
|
# Check environment variable first
|
|
if ($env:SPECIFY_FEATURE) { return $env:SPECIFY_FEATURE }
|
|
|
|
try {
|
|
$branch = git rev-parse --abbrev-ref HEAD 2>$null
|
|
if ($LASTEXITCODE -eq 0) { return $branch.Trim() }
|
|
} catch {}
|
|
|
|
# Fallback: find latest feature directory
|
|
$repoRoot = Get-RepoRoot
|
|
$specsDir = Join-Path $repoRoot "specs"
|
|
if (Test-Path $specsDir) {
|
|
$latest = Get-ChildItem -Path $specsDir -Directory |
|
|
Where-Object { $_.Name -match '^\d{3}-' } |
|
|
Sort-Object Name -Descending |
|
|
Select-Object -First 1
|
|
if ($latest) { return $latest.Name }
|
|
}
|
|
return "main"
|
|
}
|
|
|
|
function Test-HasGit {
|
|
try {
|
|
git rev-parse --show-toplevel 2>$null | Out-Null
|
|
return $LASTEXITCODE -eq 0
|
|
} catch { return $false }
|
|
}
|
|
|
|
function Test-FeatureBranch {
|
|
param([string]$Branch, [bool]$HasGit)
|
|
if (-not $HasGit) {
|
|
Write-Warning "[specify] Git repository not detected; skipped branch validation"
|
|
return $true
|
|
}
|
|
if ($Branch -notmatch '^\d{3}-') {
|
|
Write-Error "Not on a feature branch. Current branch: $Branch"
|
|
Write-Error "Feature branches should be named like: 001-feature-name"
|
|
return $false
|
|
}
|
|
return $true
|
|
}
|
|
|
|
function Find-FeatureDir {
|
|
param([string]$RepoRoot, [string]$BranchName)
|
|
$specsDir = Join-Path $RepoRoot "specs"
|
|
|
|
if ($BranchName -match '^(\d{3})-') {
|
|
$prefix = $Matches[1]
|
|
$matches = Get-ChildItem -Path $specsDir -Directory -Filter "$prefix-*" -ErrorAction SilentlyContinue
|
|
if ($matches.Count -eq 1) { return $matches[0].FullName }
|
|
if ($matches.Count -gt 1) {
|
|
Write-Warning "Multiple spec dirs with prefix '$prefix': $($matches.Name -join ', ')"
|
|
}
|
|
}
|
|
return Join-Path $specsDir $BranchName
|
|
}
|
|
|
|
function Get-FeaturePaths {
|
|
$repoRoot = Get-RepoRoot
|
|
$branch = Get-CurrentBranch
|
|
$hasGit = Test-HasGit
|
|
$featureDir = Find-FeatureDir -RepoRoot $repoRoot -BranchName $branch
|
|
|
|
return [PSCustomObject]@{
|
|
RepoRoot = $repoRoot
|
|
Branch = $branch
|
|
HasGit = $hasGit
|
|
FeatureDir = $featureDir
|
|
FeatureSpec = Join-Path $featureDir "spec.md"
|
|
ImplPlan = Join-Path $featureDir "plan.md"
|
|
Tasks = Join-Path $featureDir "tasks.md"
|
|
Research = Join-Path $featureDir "research.md"
|
|
DataModel = Join-Path $featureDir "data-model.md"
|
|
Quickstart = Join-Path $featureDir "quickstart.md"
|
|
ContractsDir = Join-Path $featureDir "contracts"
|
|
}
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Check prerequisites for Spec-Kit workflows.
|
|
.DESCRIPTION
|
|
PowerShell equivalent of .agents/scripts/bash/check-prerequisites.sh
|
|
.PARAMETER RequireTasks
|
|
Require tasks.md to exist (for implementation phase)
|
|
.PARAMETER IncludeTasks
|
|
Include tasks.md in available docs list
|
|
.PARAMETER PathsOnly
|
|
Only output paths, no validation
|
|
.EXAMPLE
|
|
.\common.ps1
|
|
$result = Check-Prerequisites -RequireTasks
|
|
#>
|
|
function Check-Prerequisites {
|
|
param(
|
|
[switch]$RequireTasks,
|
|
[switch]$IncludeTasks,
|
|
[switch]$PathsOnly
|
|
)
|
|
|
|
$paths = Get-FeaturePaths
|
|
$valid = Test-FeatureBranch -Branch $paths.Branch -HasGit $paths.HasGit
|
|
if (-not $valid) { throw "Not on a feature branch" }
|
|
|
|
if ($PathsOnly) { return $paths }
|
|
|
|
# Validate required files
|
|
if (-not (Test-Path $paths.FeatureDir)) {
|
|
throw "Feature directory not found: $($paths.FeatureDir). Run /speckit.specify first."
|
|
}
|
|
if (-not (Test-Path $paths.ImplPlan)) {
|
|
throw "plan.md not found. Run /speckit.plan first."
|
|
}
|
|
if ($RequireTasks -and -not (Test-Path $paths.Tasks)) {
|
|
throw "tasks.md not found. Run /speckit.tasks first."
|
|
}
|
|
|
|
# Build available docs list
|
|
$docs = @()
|
|
if (Test-Path $paths.Research) { $docs += "research.md" }
|
|
if (Test-Path $paths.DataModel) { $docs += "data-model.md" }
|
|
if ((Test-Path $paths.ContractsDir) -and (Get-ChildItem $paths.ContractsDir -ErrorAction SilentlyContinue)) {
|
|
$docs += "contracts/"
|
|
}
|
|
if (Test-Path $paths.Quickstart) { $docs += "quickstart.md" }
|
|
if ($IncludeTasks -and (Test-Path $paths.Tasks)) { $docs += "tasks.md" }
|
|
|
|
return [PSCustomObject]@{
|
|
FeatureDir = $paths.FeatureDir
|
|
AvailableDocs = $docs
|
|
Paths = $paths
|
|
}
|
|
}
|
|
|
|
# Export functions when dot-sourced
|
|
Export-ModuleMember -Function * -ErrorAction SilentlyContinue 2>$null
|