git_remote_htree/git/
refs.rs1use super::object::ObjectId;
6use super::{Error, Result};
7
8#[derive(Debug, Clone)]
10pub enum Ref {
11 Direct(ObjectId),
13 Symbolic(String),
15}
16
17pub fn validate_ref_name(name: &str) -> Result<()> {
19 if name.is_empty() {
20 return Err(Error::InvalidRefName("empty ref name".into()));
21 }
22
23 if name.starts_with('/') || name.ends_with('/') {
24 return Err(Error::InvalidRefName("cannot start or end with /".into()));
25 }
26
27 if name.contains("//") {
28 return Err(Error::InvalidRefName("cannot contain //".into()));
29 }
30
31 if name.contains("..") {
32 return Err(Error::InvalidRefName("cannot contain ..".into()));
33 }
34
35 for c in name.chars() {
36 if c.is_control()
37 || c == ' '
38 || c == '~'
39 || c == '^'
40 || c == ':'
41 || c == '?'
42 || c == '*'
43 || c == '['
44 {
45 return Err(Error::InvalidRefName(format!("invalid character: {:?}", c)));
46 }
47 }
48
49 if name.ends_with(".lock") {
50 return Err(Error::InvalidRefName("cannot end with .lock".into()));
51 }
52
53 if name.contains("@{") {
54 return Err(Error::InvalidRefName("cannot contain @{".into()));
55 }
56
57 if name == "@" {
58 return Err(Error::InvalidRefName("cannot be @".into()));
59 }
60
61 if name.ends_with('.') {
62 return Err(Error::InvalidRefName("cannot end with .".into()));
63 }
64
65 Ok(())
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 #[test]
73 fn test_valid_ref_names() {
74 assert!(validate_ref_name("refs/heads/main").is_ok());
75 assert!(validate_ref_name("refs/heads/feature/test").is_ok());
76 assert!(validate_ref_name("refs/tags/v1.0.0").is_ok());
77 assert!(validate_ref_name("HEAD").is_ok());
78 }
79
80 #[test]
81 fn test_invalid_ref_names() {
82 assert!(validate_ref_name("").is_err());
83 assert!(validate_ref_name("/refs/heads/main").is_err());
84 assert!(validate_ref_name("refs/heads/main/").is_err());
85 assert!(validate_ref_name("refs//heads").is_err());
86 assert!(validate_ref_name("refs/heads/..").is_err());
87 assert!(validate_ref_name("refs/heads/test.lock").is_err());
88 assert!(validate_ref_name("refs/heads/te st").is_err());
89 }
90}