diff options
| author | 2026-03-07 15:08:14 +0800 | |
|---|---|---|
| committer | 2026-03-07 15:56:39 +0800 | |
| commit | 9d08dc994d51298e2d8e75d8ed4ee477312ec53a (patch) | |
| tree | 28c2a53174dd319fbd330132d446ef9ead8cb7ee /ref/refname/validate.go | |
| parent | refstore: Remove Shorten for now (diff) | |
| signature | No signature | |
ref/refname: Add refname validation
Diffstat (limited to 'ref/refname/validate.go')
| -rw-r--r-- | ref/refname/validate.go | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/ref/refname/validate.go b/ref/refname/validate.go new file mode 100644 index 00000000..1b8ad396 --- /dev/null +++ b/ref/refname/validate.go @@ -0,0 +1,65 @@ +package refname + +import "strings" + +// Validate checks whether name is one valid Git refname. +func Validate(name string, options Options) error { + return validate(name, options.flags()) +} + +func validate(name string, flags int) error { + return checkOrSanitizeRefname(name, flags, nil) +} + +func checkOrSanitizeRefname(name string, flags int, sanitized *strings.Builder) error { + componentCount := 0 + remaining := name + + if name == "@" { + if sanitized == nil { + return &NameError{Name: name, Reason: "single @ is not allowed"} + } + + sanitized.WriteByte('-') + } + + for { + if sanitized != nil && sanitized.Len() > 0 { + sanitized.WriteByte('/') + } + + componentLen, err := checkRefnameComponent(remaining, &flags, sanitized, name) + switch { + case sanitized != nil && componentLen == 0: + case componentLen <= 0: + if err != nil { + return err + } + + return &NameError{Name: name, Reason: "component has zero length"} + case err != nil: + return err + } + + componentCount++ + + if componentLen == len(remaining) { + break + } + + remaining = remaining[componentLen+1:] + } + + componentLen := len(remaining) + if componentLen > 0 && remaining[componentLen-1] == '.' { + if sanitized == nil { + return &NameError{Name: name, Reason: "name ends with '.'"} + } + } + + if flags&refnameAllowOneLevel == 0 && componentCount < 2 { + return &NameError{Name: name, Reason: "one-level refname is not allowed"} + } + + return nil +} |
