fix(import): support hierarchical hash IDs in --rename-on-import
The isNumeric function was rejecting valid hierarchical hash IDs like '6we.2' that contain dots for parent.child notation. This caused `bd import --rename-on-import` to fail with "non-numeric suffix" errors. Changes: - Rename isNumeric to isValidIDSuffix for clarity - Accept dots (.) in addition to alphanumeric for hierarchical IDs - Update test cases to cover hierarchical ID formats
This commit is contained in:
@@ -524,7 +524,7 @@ func TestIsBoundary(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsNumeric(t *testing.T) {
|
||||
func TestIsValidIDSuffix(t *testing.T) {
|
||||
tests := []struct {
|
||||
s string
|
||||
want bool
|
||||
@@ -538,18 +538,24 @@ func TestIsNumeric(t *testing.T) {
|
||||
{"09ea", true},
|
||||
{"abc123", true},
|
||||
{"zzz", true},
|
||||
// Hierarchical suffixes (hash.number format)
|
||||
{"6we.2", true},
|
||||
{"abc.1", true},
|
||||
{"abc.1.2", true},
|
||||
{"abc.1.2.3", true},
|
||||
{"1.5", true},
|
||||
// Invalid suffixes
|
||||
{"", false}, // Empty string now returns false
|
||||
{"1.5", false}, // Non-base36 characters
|
||||
{"A3F8", false}, // Uppercase not allowed
|
||||
{"@#$!", false}, // Special characters not allowed
|
||||
{"", false}, // Empty string
|
||||
{"A3F8", false}, // Uppercase not allowed
|
||||
{"@#$!", false}, // Special characters not allowed
|
||||
{"abc-def", false}, // Hyphens not allowed in suffix
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.s, func(t *testing.T) {
|
||||
got := isNumeric(tt.s)
|
||||
got := isValidIDSuffix(tt.s)
|
||||
if got != tt.want {
|
||||
t.Errorf("isNumeric(%q) = %v, want %v", tt.s, got, tt.want)
|
||||
t.Errorf("isValidIDSuffix(%q) = %v, want %v", tt.s, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -151,15 +151,15 @@ func RenameImportedIssuePrefixes(issues []*types.Issue, targetPrefix string) err
|
||||
}
|
||||
|
||||
if oldPrefix != targetPrefix {
|
||||
// Extract the numeric part
|
||||
numPart := strings.TrimPrefix(issue.ID, oldPrefix+"-")
|
||||
// Extract the suffix part (supports both numeric "123" and hash "abc1" and hierarchical "abc.1.2")
|
||||
suffix := strings.TrimPrefix(issue.ID, oldPrefix+"-")
|
||||
|
||||
// Validate that the numeric part is actually numeric
|
||||
if numPart == "" || !isNumeric(numPart) {
|
||||
return fmt.Errorf("cannot rename issue %s: non-numeric suffix '%s'", issue.ID, numPart)
|
||||
// Validate that the suffix is valid (alphanumeric + dots for hierarchy)
|
||||
if suffix == "" || !isValidIDSuffix(suffix) {
|
||||
return fmt.Errorf("cannot rename issue %s: invalid suffix '%s'", issue.ID, suffix)
|
||||
}
|
||||
|
||||
newID := fmt.Sprintf("%s-%s", targetPrefix, numPart)
|
||||
newID := fmt.Sprintf("%s-%s", targetPrefix, suffix)
|
||||
idMapping[issue.ID] = newID
|
||||
}
|
||||
}
|
||||
@@ -270,13 +270,15 @@ func isBoundary(c byte) bool {
|
||||
return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == ',' || c == '.' || c == '!' || c == '?' || c == ':' || c == ';' || c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}'
|
||||
}
|
||||
|
||||
func isNumeric(s string) bool {
|
||||
// isValidIDSuffix checks if a string is a valid issue ID suffix
|
||||
// Accepts: digits (0-9), lowercase letters (a-z), and dots (.) for hierarchy
|
||||
// Examples: "123", "abc1", "6we", "6we.2", "abc.1.2"
|
||||
func isValidIDSuffix(s string) bool {
|
||||
if len(s) == 0 {
|
||||
return false
|
||||
}
|
||||
// Accept base36 characters (0-9, a-z) for hash-based suffixes
|
||||
for _, c := range s {
|
||||
if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z')) {
|
||||
if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || c == '.') {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user