mirror of
https://github.com/github/spec-kit.git
synced 2026-03-25 14:53:08 +00:00
fix(scripts): prioritize .specify over git for repo root detection (#1933)
* fix(scripts): prioritize .specify over git for repo root detection When spec-kit is initialized in a subdirectory that doesn't have its own .git, but a parent directory does, spec-kit was incorrectly using the parent's git repository root. This caused specs to be created in the wrong location. The fix changes repo root detection to prioritize .specify directory over git rev-parse, ensuring spec-kit respects its own initialization boundary rather than inheriting a parent git repo. Fixes #1932 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: address code review feedback - Normalize paths in find_specify_root to prevent infinite loop with relative paths - Use -PathType Container in PowerShell to only match .specify directories - Improve has_git/Test-HasGit to check git command availability and validate work tree - Handle git worktrees/submodules where .git can be a file - Remove dead fallback code in create-new-feature scripts Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: check .specify before termination in find_specify_root Fixes edge case where project root is at filesystem root (common in containers). The loop now checks for .specify before checking the termination condition. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: scope git operations to spec-kit root & remove unused helpers - get_current_branch now uses has_git check and runs git with -C to prevent using parent git repo branch names in .specify-only projects - Same fix applied to PowerShell Get-CurrentBranch - Removed unused find_repo_root() from create-new-feature.sh - Removed unused Find-RepositoryRoot from create-new-feature.ps1 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: use cd -- to handle paths starting with dash Prevents cd from interpreting directory names like -P or -L as options. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: check git command exists before calling get_repo_root in has_git Avoids unnecessary work when git isn't installed since get_repo_root may internally call git rev-parse. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(powershell): use LiteralPath and check git before Get-RepoRoot - Use -LiteralPath in Find-SpecifyRoot to handle paths with wildcard characters ([, ], *, ?) - Check Get-Command git before calling Get-RepoRoot in Test-HasGit to avoid unnecessary work when git isn't installed Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(powershell): use LiteralPath for .git check in Test-HasGit Prevents Test-Path from treating wildcard characters in paths as globs. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(powershell): use LiteralPath in Get-RepoRoot fallback Prevents Resolve-Path from treating wildcard characters as patterns. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: iamaeroplane <michal.bachorik@gmail.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,38 @@
|
||||
#!/usr/bin/env pwsh
|
||||
# Common PowerShell functions analogous to common.sh
|
||||
|
||||
# Find repository root by searching upward for .specify directory
|
||||
# This is the primary marker for spec-kit projects
|
||||
function Find-SpecifyRoot {
|
||||
param([string]$StartDir = (Get-Location).Path)
|
||||
|
||||
# Normalize to absolute path to prevent issues with relative paths
|
||||
# Use -LiteralPath to handle paths with wildcard characters ([, ], *, ?)
|
||||
$current = (Resolve-Path -LiteralPath $StartDir -ErrorAction SilentlyContinue)?.Path
|
||||
if (-not $current) { return $null }
|
||||
|
||||
while ($true) {
|
||||
if (Test-Path -LiteralPath (Join-Path $current ".specify") -PathType Container) {
|
||||
return $current
|
||||
}
|
||||
$parent = Split-Path $current -Parent
|
||||
if ([string]::IsNullOrEmpty($parent) -or $parent -eq $current) {
|
||||
return $null
|
||||
}
|
||||
$current = $parent
|
||||
}
|
||||
}
|
||||
|
||||
# Get repository root, prioritizing .specify directory over git
|
||||
# This prevents using a parent git repo when spec-kit is initialized in a subdirectory
|
||||
function Get-RepoRoot {
|
||||
# First, look for .specify directory (spec-kit's own marker)
|
||||
$specifyRoot = Find-SpecifyRoot
|
||||
if ($specifyRoot) {
|
||||
return $specifyRoot
|
||||
}
|
||||
|
||||
# Fallback to git if no .specify found
|
||||
try {
|
||||
$result = git rev-parse --show-toplevel 2>$null
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
@@ -10,9 +41,10 @@ function Get-RepoRoot {
|
||||
} catch {
|
||||
# Git command failed
|
||||
}
|
||||
|
||||
# Fall back to script location for non-git repos
|
||||
return (Resolve-Path (Join-Path $PSScriptRoot "../../..")).Path
|
||||
|
||||
# Final fallback to script location for non-git repos
|
||||
# Use -LiteralPath to handle paths with wildcard characters
|
||||
return (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "../../..")).Path
|
||||
}
|
||||
|
||||
function Get-CurrentBranch {
|
||||
@@ -20,19 +52,21 @@ function Get-CurrentBranch {
|
||||
if ($env:SPECIFY_FEATURE) {
|
||||
return $env:SPECIFY_FEATURE
|
||||
}
|
||||
|
||||
# Then check git if available
|
||||
try {
|
||||
$result = git rev-parse --abbrev-ref HEAD 2>$null
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
return $result
|
||||
}
|
||||
} catch {
|
||||
# Git command failed
|
||||
}
|
||||
|
||||
# For non-git repos, try to find the latest feature directory
|
||||
|
||||
# Then check git if available at the spec-kit root (not parent)
|
||||
$repoRoot = Get-RepoRoot
|
||||
if (Test-HasGit) {
|
||||
try {
|
||||
$result = git -C $repoRoot rev-parse --abbrev-ref HEAD 2>$null
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
return $result
|
||||
}
|
||||
} catch {
|
||||
# Git command failed
|
||||
}
|
||||
}
|
||||
|
||||
# For non-git repos, try to find the latest feature directory
|
||||
$specsDir = Join-Path $repoRoot "specs"
|
||||
|
||||
if (Test-Path $specsDir) {
|
||||
@@ -69,9 +103,23 @@ function Get-CurrentBranch {
|
||||
return "main"
|
||||
}
|
||||
|
||||
# Check if we have git available at the spec-kit root level
|
||||
# Returns true only if git is installed and the repo root is inside a git work tree
|
||||
# Handles both regular repos (.git directory) and worktrees/submodules (.git file)
|
||||
function Test-HasGit {
|
||||
# First check if git command is available (before calling Get-RepoRoot which may use git)
|
||||
if (-not (Get-Command git -ErrorAction SilentlyContinue)) {
|
||||
return $false
|
||||
}
|
||||
$repoRoot = Get-RepoRoot
|
||||
# Check if .git exists (directory or file for worktrees/submodules)
|
||||
# Use -LiteralPath to handle paths with wildcard characters
|
||||
if (-not (Test-Path -LiteralPath (Join-Path $repoRoot ".git"))) {
|
||||
return $false
|
||||
}
|
||||
# Verify it's actually a valid git work tree
|
||||
try {
|
||||
git rev-parse --show-toplevel 2>$null | Out-Null
|
||||
$null = git -C $repoRoot rev-parse --is-inside-work-tree 2>$null
|
||||
return ($LASTEXITCODE -eq 0)
|
||||
} catch {
|
||||
return $false
|
||||
|
||||
Reference in New Issue
Block a user