File view with blame information shown in the left gutter beside each line.

barerepo / server / internal/gitx/names.go
109 lines · 3.2kb · 133728eaa05486504991b230f9d4c7e986b7defc
log files threads runs releases config jump to file t
133728e barerepo 1mo
1
package gitx
133728e barerepo 1mo
2
133728e barerepo 1mo
3
import (
133728e barerepo 1mo
4
"regexp"
133728e barerepo 1mo
5
"strings"
133728e barerepo 1mo
6
)
133728e barerepo 1mo
7
133728e barerepo 1mo
8
// namePattern is the one rule for account and repository names alike. Chapter 42.5.
133728e barerepo 1mo
9
var namePattern = regexp.MustCompile(`^[a-z0-9][a-z0-9-]{0,38}$`)
133728e barerepo 1mo
10
133728e barerepo 1mo
11
// reserved holds every top-level route name, which TestEveryTopLevelRouteIsAReservedName derives.
133728e barerepo 1mo
12
var reserved = map[string]bool{
133728e barerepo 1mo
13
// routed today, per appendix C
133728e barerepo 1mo
14
"new": true, "signup": true, "signin": true, "signout": true, "auth": true,
133728e barerepo 1mo
15
"keys": true, "gpgkeys": true, "tokens": true, "search": true, "inbox": true,
133728e barerepo 1mo
16
"runner": true, "raw": true,
133728e barerepo 1mo
17
// held for later
133728e barerepo 1mo
18
"static": true, "api": true, "admin": true, "about": true, "card": true,
133728e barerepo 1mo
19
}
133728e barerepo 1mo
20
133728e barerepo 1mo
21
// ValidName reports whether s is a usable account name, which a top-level route can shadow.
133728e barerepo 1mo
22
func ValidName(s string) bool {
133728e barerepo 1mo
23
return namePattern.MatchString(s) && !reserved[s]
133728e barerepo 1mo
24
}
133728e barerepo 1mo
25
133728e barerepo 1mo
26
// ValidRepoName drops the reserved list, because a repository is a second path segment and every reserved name is a first one.
133728e barerepo 1mo
27
func ValidRepoName(s string) bool {
133728e barerepo 1mo
28
return namePattern.MatchString(s)
133728e barerepo 1mo
29
}
133728e barerepo 1mo
30
133728e barerepo 1mo
31
// Reserved reports a name refused only because a route owns it, which signup says out loud.
133728e barerepo 1mo
32
func Reserved(s string) bool { return reserved[s] }
133728e barerepo 1mo
33
133728e barerepo 1mo
34
// ValidRef mirrors check-ref-format and runs first, so nothing malformed reaches an argument.
133728e barerepo 1mo
35
func ValidRef(r string) bool {
133728e barerepo 1mo
36
if r == "" || len(r) > 255 {
133728e barerepo 1mo
37
return false
133728e barerepo 1mo
38
}
133728e barerepo 1mo
39
if strings.HasSuffix(r, "/") || strings.HasSuffix(r, ".lock") {
133728e barerepo 1mo
40
return false
133728e barerepo 1mo
41
}
133728e barerepo 1mo
42
if strings.Contains(r, "..") || strings.Contains(r, "@{") || strings.Contains(r, "//") {
133728e barerepo 1mo
43
return false
133728e barerepo 1mo
44
}
133728e barerepo 1mo
45
if strings.ContainsAny(r, " ~^:?*[\\\x7f") {
133728e barerepo 1mo
46
return false
133728e barerepo 1mo
47
}
133728e barerepo 1mo
48
for _, c := range r {
133728e barerepo 1mo
49
if c < 0x20 {
133728e barerepo 1mo
50
return false
133728e barerepo 1mo
51
}
133728e barerepo 1mo
52
}
133728e barerepo 1mo
53
for _, part := range strings.Split(r, "/") {
133728e barerepo 1mo
54
if part == "" || strings.HasPrefix(part, ".") || strings.HasSuffix(part, ".") {
133728e barerepo 1mo
55
return false
133728e barerepo 1mo
56
}
133728e barerepo 1mo
57
// Any component, because git is handed the component alone and a dash makes it a flag.
133728e barerepo 1mo
58
if strings.HasPrefix(part, "-") {
133728e barerepo 1mo
59
return false
133728e barerepo 1mo
60
}
133728e barerepo 1mo
61
}
133728e barerepo 1mo
62
return true
133728e barerepo 1mo
63
}
133728e barerepo 1mo
64
133728e barerepo 1mo
65
// ValidRev guards a revision from a URL, and above all stops a leading dash becoming a flag.
133728e barerepo 1mo
66
func ValidRev(r string) bool {
133728e barerepo 1mo
67
if r == "" || len(r) > 255 {
133728e barerepo 1mo
68
return false
133728e barerepo 1mo
69
}
133728e barerepo 1mo
70
if strings.HasPrefix(r, "-") || strings.Contains(r, "..") && !strings.Contains(r, "...") {
133728e barerepo 1mo
71
// Callers build their own ranges, and the compare view splits `...` before it gets here.
133728e barerepo 1mo
72
return false
133728e barerepo 1mo
73
}
133728e barerepo 1mo
74
if strings.Contains(r, "...") {
133728e barerepo 1mo
75
return false
133728e barerepo 1mo
76
}
133728e barerepo 1mo
77
for _, c := range r {
133728e barerepo 1mo
78
switch {
133728e barerepo 1mo
79
case c >= 'a' && c <= 'z', c >= 'A' && c <= 'Z', c >= '0' && c <= '9':
133728e barerepo 1mo
80
case c == '/' || c == '.' || c == '-' || c == '_' || c == '~' || c == '^' || c == '@':
133728e barerepo 1mo
81
default:
133728e barerepo 1mo
82
return false
133728e barerepo 1mo
83
}
133728e barerepo 1mo
84
}
133728e barerepo 1mo
85
for _, part := range strings.Split(r, "/") {
133728e barerepo 1mo
86
if part == "" || strings.HasPrefix(part, ".") || strings.HasPrefix(part, "-") {
133728e barerepo 1mo
87
return false
133728e barerepo 1mo
88
}
133728e barerepo 1mo
89
}
133728e barerepo 1mo
90
return true
133728e barerepo 1mo
91
}
133728e barerepo 1mo
92
133728e barerepo 1mo
93
// ValidPath guards a path in a git tree against the same two mistakes: escaping up, and flags.
133728e barerepo 1mo
94
func ValidPath(p string) bool {
133728e barerepo 1mo
95
if p == "" || len(p) > 4096 || strings.HasPrefix(p, "-") || strings.HasPrefix(p, "/") {
133728e barerepo 1mo
96
return false
133728e barerepo 1mo
97
}
133728e barerepo 1mo
98
for _, part := range strings.Split(p, "/") {
133728e barerepo 1mo
99
if part == "" || part == "." || part == ".." {
133728e barerepo 1mo
100
return false
133728e barerepo 1mo
101
}
133728e barerepo 1mo
102
}
133728e barerepo 1mo
103
for _, c := range p {
133728e barerepo 1mo
104
if c < 0x20 || c == 0x7f {
133728e barerepo 1mo
105
return false
133728e barerepo 1mo
106
}
133728e barerepo 1mo
107
}
133728e barerepo 1mo
108
return true
133728e barerepo 1mo
109
}
history · rawbarerepo 0.1.0