g1t/crates/contracts/src/names.rs

58 lines1,376 bytesCodeBlame
1/// Routes and reserved words that may not be registered as usernames.
2const RESERVED: &[&str] = &[
3 "api",
4 "mcp",
5 "login",
6 "logout",
7 "register",
8 "new",
9 "settings",
10 "search",
11 "admin",
12 "auth",
13 "attempts",
14 "oauth",
15 "assets",
16 "docs",
17 "explore",
18 "g1t",
19 "about",
20 "pricing",
21 "terms",
22 "privacy",
23 "help",
24 "support",
25 "status",
26 "blog",
27 "verify",
28 "forgot",
29 "reset",
30 "device",
31 "workspaces",
32 "u",
33];
34
35/// Namespaces follow GitHub's rules: letters, digits and single hyphens,
36/// not starting or ending with a hyphen, at most 39 characters.
37pub fn is_valid_namespace(value: &str) -> bool {
38 let bytes = value.as_bytes();
39 !bytes.is_empty()
40 && bytes.len() <= 39
41 && bytes
42 .iter()
43 .all(|byte| byte.is_ascii_lowercase() || byte.is_ascii_digit() || *byte == b'-')
44 && !value.starts_with('-')
45 && !value.ends_with('-')
46 && !value.contains("--")
47 && !RESERVED.contains(&value)
48}
49
50pub fn is_valid_repo_name(value: &str) -> bool {
51 !value.is_empty()
52 && value.len() <= 100
53 && value.bytes().all(|byte| {
54 byte.is_ascii_lowercase() || byte.is_ascii_digit() || matches!(byte, b'.' | b'_' | b'-')
55 })
56 && !value.starts_with('.')
57 && !value.ends_with(".git")
58}