Merge bd-6xfz-furiosa: GH#405 prefix parsing
This commit is contained in:
1797
.beads/issues.jsonl
1797
.beads/issues.jsonl
File diff suppressed because one or more lines are too long
@@ -360,7 +360,7 @@ func TestExtractIssuePrefix(t *testing.T) {
|
||||
{
|
||||
name: "multi-part non-numeric suffix",
|
||||
issueID: "vc-baseline-test",
|
||||
expected: "vc", // Falls back to first hyphen for non-numeric suffix
|
||||
expected: "vc-baseline", // Alphanumeric suffix uses last hyphen (GH#405 fix)
|
||||
},
|
||||
{
|
||||
name: "beads-vscode style prefix",
|
||||
|
||||
@@ -43,16 +43,18 @@ func TestExtractIssuePrefixAllLetterHash(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestExtractIssuePrefixWordSuffix ensures 4+ char word suffixes still work
|
||||
// TestExtractIssuePrefixWordSuffix tests alphanumeric suffixes (GH#405 fix)
|
||||
// With the GH#405 fix, all alphanumeric suffixes use last-hyphen extraction,
|
||||
// even if they look like English words. This fixes multi-hyphen prefix parsing.
|
||||
func TestExtractIssuePrefixWordSuffix(t *testing.T) {
|
||||
// These should use first-hyphen extraction (word suffixes, not hashes)
|
||||
// These should use last-hyphen extraction (alphanumeric = valid issue ID suffix)
|
||||
wordSuffixes := []struct {
|
||||
issueID string
|
||||
expected string
|
||||
}{
|
||||
{"vc-baseline-test", "vc"}, // 4-char "test" - word, not hash
|
||||
{"vc-baseline-hello", "vc"}, // 5-char word
|
||||
{"vc-some-feature", "vc"}, // multi-word suffix
|
||||
{"vc-baseline-test", "vc-baseline"}, // GH#405: alphanumeric suffix uses last hyphen
|
||||
{"vc-baseline-hello", "vc-baseline"}, // GH#405: alphanumeric suffix uses last hyphen
|
||||
{"vc-some-feature", "vc-some"}, // GH#405: alphanumeric suffix uses last hyphen
|
||||
}
|
||||
|
||||
for _, tc := range wordSuffixes {
|
||||
|
||||
@@ -6,11 +6,14 @@ import (
|
||||
)
|
||||
|
||||
// ExtractIssuePrefix extracts the prefix from an issue ID like "bd-123" -> "bd"
|
||||
// Uses the last hyphen before a numeric or hash suffix:
|
||||
// Uses the last hyphen before an alphanumeric suffix:
|
||||
// - "beads-vscode-1" -> "beads-vscode" (numeric suffix)
|
||||
// - "web-app-a3f8e9" -> "web-app" (hash suffix)
|
||||
// - "my-cool-app-123" -> "my-cool-app" (numeric suffix)
|
||||
// Only uses first hyphen for non-ID suffixes like "vc-baseline-test" -> "vc"
|
||||
// - "hacker-news-test" -> "hacker-news" (alphanumeric suffix, GH#405)
|
||||
//
|
||||
// Only uses first hyphen when suffix contains non-alphanumeric characters,
|
||||
// which indicates it's not an issue ID but something like a project name.
|
||||
func ExtractIssuePrefix(issueID string) string {
|
||||
// Try last hyphen first (handles multi-part prefixes like "beads-vscode-1")
|
||||
lastIdx := strings.LastIndex(issueID, "-")
|
||||
@@ -19,30 +22,35 @@ func ExtractIssuePrefix(issueID string) string {
|
||||
}
|
||||
|
||||
suffix := issueID[lastIdx+1:]
|
||||
// Check if suffix looks like an issue ID component (numeric or hash-like)
|
||||
if len(suffix) > 0 {
|
||||
// Extract just the numeric part (handle "123.1.2" -> check "123")
|
||||
numPart := suffix
|
||||
if dotIdx := strings.Index(suffix, "."); dotIdx > 0 {
|
||||
numPart = suffix[:dotIdx]
|
||||
}
|
||||
if len(suffix) == 0 {
|
||||
// Trailing hyphen like "bd-" - return prefix before the hyphen
|
||||
return issueID[:lastIdx]
|
||||
}
|
||||
|
||||
// Check if it's numeric
|
||||
var num int
|
||||
if _, err := fmt.Sscanf(numPart, "%d", &num); err == nil {
|
||||
// Suffix is numeric, use last hyphen
|
||||
return issueID[:lastIdx]
|
||||
}
|
||||
// Extract the base part before any dot (handle "123.1.2" -> check "123")
|
||||
basePart := suffix
|
||||
if dotIdx := strings.Index(suffix, "."); dotIdx > 0 {
|
||||
basePart = suffix[:dotIdx]
|
||||
}
|
||||
|
||||
// Check if it looks like a hash (hexadecimal characters, 4+ chars)
|
||||
// Hash IDs are typically 4-8 hex characters (e.g., "a3f8e9", "1a2b")
|
||||
if isLikelyHash(numPart) {
|
||||
// Suffix looks like a hash, use last hyphen
|
||||
return issueID[:lastIdx]
|
||||
// Check if basePart is alphanumeric (valid issue ID suffix)
|
||||
// Issue IDs are always alphanumeric: numeric (1, 23) or hash (a3f, xyz, test)
|
||||
isAlphanumeric := len(basePart) > 0
|
||||
for _, c := range basePart {
|
||||
if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
|
||||
isAlphanumeric = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Suffix is not numeric or hash-like (e.g., "vc-baseline-test"), fall back to first hyphen
|
||||
// If suffix is alphanumeric, this is an issue ID - use last hyphen
|
||||
// This handles all issue ID formats including word-like hashes (GH#405)
|
||||
if isAlphanumeric {
|
||||
return issueID[:lastIdx]
|
||||
}
|
||||
|
||||
// Suffix contains special characters - not a standard issue ID
|
||||
// Fall back to first hyphen for cases like project names with descriptions
|
||||
firstIdx := strings.Index(issueID, "-")
|
||||
if firstIdx <= 0 {
|
||||
return ""
|
||||
|
||||
Reference in New Issue
Block a user