|
3 | 3 | [CmdletBinding()] |
4 | 4 | param( |
5 | 5 | [switch]$Json, |
| 6 | + [string]$ShortName, |
6 | 7 | [Parameter(ValueFromRemainingArguments = $true)] |
7 | 8 | [string[]]$FeatureDescription |
8 | 9 | ) |
9 | 10 | $ErrorActionPreference = 'Stop' |
10 | 11 |
|
11 | | -if (-not $FeatureDescription -or $FeatureDescription.Count -eq 0) { |
12 | | - Write-Error "Usage: ./create-new-feature.ps1 [-Json] <feature description>" |
13 | | - exit 1 |
| 12 | +# Show help if requested or no description provided |
| 13 | +if (($FeatureDescription -contains '--help') -or ($FeatureDescription -contains '-h') -or |
| 14 | + (-not $FeatureDescription) -or ($FeatureDescription.Count -eq 0)) { |
| 15 | + |
| 16 | + if (($FeatureDescription -contains '--help') -or ($FeatureDescription -contains '-h')) { |
| 17 | + Write-Host "Usage: ./create-new-feature.ps1 [-Json] [-ShortName <name>] <feature description>" |
| 18 | + Write-Host "" |
| 19 | + Write-Host "Options:" |
| 20 | + Write-Host " -Json Output in JSON format" |
| 21 | + Write-Host " -ShortName <name> Provide a custom short name (2-4 words) for the branch" |
| 22 | + Write-Host " -h, --help Show this help message" |
| 23 | + Write-Host "" |
| 24 | + Write-Host "Examples:" |
| 25 | + Write-Host " ./create-new-feature.ps1 'Add user authentication system' -ShortName 'user-auth'" |
| 26 | + Write-Host " ./create-new-feature.ps1 'Implement OAuth2 integration for API'" |
| 27 | + exit 0 |
| 28 | + } else { |
| 29 | + Write-Error "Usage: ./create-new-feature.ps1 [-Json] [-ShortName <name>] <feature description>" |
| 30 | + exit 1 |
| 31 | + } |
14 | 32 | } |
| 33 | + |
15 | 34 | $featureDesc = ($FeatureDescription -join ' ').Trim() |
16 | 35 |
|
17 | 36 | # Resolve repository root. Prefer git information when available, but fall back |
@@ -72,9 +91,82 @@ if (Test-Path $specsDir) { |
72 | 91 | $next = $highest + 1 |
73 | 92 | $featureNum = ('{0:000}' -f $next) |
74 | 93 |
|
75 | | -$branchName = $featureDesc.ToLower() -replace '[^a-z0-9]', '-' -replace '-{2,}', '-' -replace '^-', '' -replace '-$', '' |
76 | | -$words = ($branchName -split '-') | Where-Object { $_ } | Select-Object -First 3 |
77 | | -$branchName = "$featureNum-$([string]::Join('-', $words))" |
| 94 | +# Function to generate branch name with stop word filtering and length filtering |
| 95 | +function Get-BranchName { |
| 96 | + param([string]$Description) |
| 97 | + |
| 98 | + # Common stop words to filter out |
| 99 | + $stopWords = @( |
| 100 | + 'i', 'a', 'an', 'the', 'to', 'for', 'of', 'in', 'on', 'at', 'by', 'with', 'from', |
| 101 | + 'is', 'are', 'was', 'were', 'be', 'been', 'being', 'have', 'has', 'had', |
| 102 | + 'do', 'does', 'did', 'will', 'would', 'should', 'could', 'can', 'may', 'might', 'must', 'shall', |
| 103 | + 'this', 'that', 'these', 'those', 'my', 'your', 'our', 'their', |
| 104 | + 'want', 'need', 'add', 'get', 'set' |
| 105 | + ) |
| 106 | + |
| 107 | + # Convert to lowercase and extract words (alphanumeric only) |
| 108 | + $cleanName = $Description.ToLower() -replace '[^a-z0-9\s]', ' ' |
| 109 | + $words = $cleanName -split '\s+' | Where-Object { $_ } |
| 110 | + |
| 111 | + # Filter words: remove stop words and words shorter than 3 chars (unless they're uppercase acronyms in original) |
| 112 | + $meaningfulWords = @() |
| 113 | + foreach ($word in $words) { |
| 114 | + # Skip stop words |
| 115 | + if ($stopWords -contains $word) { continue } |
| 116 | + |
| 117 | + # Keep words that are length >= 3 OR appear as uppercase in original (likely acronyms) |
| 118 | + if ($word.Length -ge 3) { |
| 119 | + $meaningfulWords += $word |
| 120 | + } elseif ($Description -match "\b$($word.ToUpper())\b") { |
| 121 | + # Keep short words if they appear as uppercase in original (likely acronyms) |
| 122 | + $meaningfulWords += $word |
| 123 | + } |
| 124 | + } |
| 125 | + |
| 126 | + # If we have meaningful words, use first 3-4 of them |
| 127 | + if ($meaningfulWords.Count -gt 0) { |
| 128 | + $maxWords = if ($meaningfulWords.Count -eq 4) { 4 } else { 3 } |
| 129 | + $result = ($meaningfulWords | Select-Object -First $maxWords) -join '-' |
| 130 | + return $result |
| 131 | + } else { |
| 132 | + # Fallback to original logic if no meaningful words found |
| 133 | + $result = $Description.ToLower() -replace '[^a-z0-9]', '-' -replace '-{2,}', '-' -replace '^-', '' -replace '-$', '' |
| 134 | + $fallbackWords = ($result -split '-') | Where-Object { $_ } | Select-Object -First 3 |
| 135 | + return [string]::Join('-', $fallbackWords) |
| 136 | + } |
| 137 | +} |
| 138 | + |
| 139 | +# Generate branch name |
| 140 | +if ($ShortName) { |
| 141 | + # Use provided short name, just clean it up |
| 142 | + $branchSuffix = $ShortName.ToLower() -replace '[^a-z0-9]', '-' -replace '-{2,}', '-' -replace '^-', '' -replace '-$', '' |
| 143 | +} else { |
| 144 | + # Generate from description with smart filtering |
| 145 | + $branchSuffix = Get-BranchName -Description $featureDesc |
| 146 | +} |
| 147 | + |
| 148 | +$branchName = "$featureNum-$branchSuffix" |
| 149 | + |
| 150 | +# GitHub enforces a 244-byte limit on branch names |
| 151 | +# Validate and truncate if necessary |
| 152 | +$maxBranchLength = 244 |
| 153 | +if ($branchName.Length -gt $maxBranchLength) { |
| 154 | + # Calculate how much we need to trim from suffix |
| 155 | + # Account for: feature number (3) + hyphen (1) = 4 chars |
| 156 | + $maxSuffixLength = $maxBranchLength - 4 |
| 157 | + |
| 158 | + # Truncate suffix |
| 159 | + $truncatedSuffix = $branchSuffix.Substring(0, [Math]::Min($branchSuffix.Length, $maxSuffixLength)) |
| 160 | + # Remove trailing hyphen if truncation created one |
| 161 | + $truncatedSuffix = $truncatedSuffix -replace '-$', '' |
| 162 | + |
| 163 | + $originalBranchName = $branchName |
| 164 | + $branchName = "$featureNum-$truncatedSuffix" |
| 165 | + |
| 166 | + Write-Warning "[specify] Branch name exceeded GitHub's 244-byte limit" |
| 167 | + Write-Warning "[specify] Original: $originalBranchName ($($originalBranchName.Length) bytes)" |
| 168 | + Write-Warning "[specify] Truncated to: $branchName ($($branchName.Length) bytes)" |
| 169 | +} |
78 | 170 |
|
79 | 171 | if ($hasGit) { |
80 | 172 | try { |
|
0 commit comments