rustic_git/
types.rs

1/// Represents a Git object hash (commit, tree, blob, etc.).
2#[derive(Debug, Clone, PartialEq, Eq)]
3pub struct Hash(pub String);
4
5impl Hash {
6    /// Get the hash as a string slice.
7    pub fn as_str(&self) -> &str {
8        &self.0
9    }
10
11    /// Get the short version of the hash (first 7 characters).
12    pub fn short(&self) -> &str {
13        if self.0.len() >= 7 {
14            &self.0[..7]
15        } else {
16            &self.0
17        }
18    }
19}
20
21impl std::fmt::Display for Hash {
22    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23        write!(f, "{}", self.0)
24    }
25}
26
27impl From<String> for Hash {
28    fn from(s: String) -> Self {
29        Hash(s)
30    }
31}
32
33impl From<&str> for Hash {
34    fn from(s: &str) -> Self {
35        Hash(s.to_string())
36    }
37}
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42
43    #[test]
44    fn test_hash_creation() {
45        let hash = Hash("abc123def456".to_string());
46        assert_eq!(hash.0, "abc123def456");
47    }
48
49    #[test]
50    fn test_hash_as_str() {
51        let hash = Hash("abc123def456".to_string());
52        assert_eq!(hash.as_str(), "abc123def456");
53    }
54
55    #[test]
56    fn test_hash_short_full_length() {
57        let hash = Hash("abc123def456".to_string());
58        assert_eq!(hash.short(), "abc123d");
59    }
60
61    #[test]
62    fn test_hash_short_exactly_seven() {
63        let hash = Hash("abcdefg".to_string());
64        assert_eq!(hash.short(), "abcdefg");
65    }
66
67    #[test]
68    fn test_hash_short_less_than_seven() {
69        let hash = Hash("abc".to_string());
70        assert_eq!(hash.short(), "abc");
71    }
72
73    #[test]
74    fn test_hash_short_empty() {
75        let hash = Hash("".to_string());
76        assert_eq!(hash.short(), "");
77    }
78
79    #[test]
80    fn test_hash_display() {
81        let hash = Hash("abc123def456".to_string());
82        assert_eq!(format!("{}", hash), "abc123def456");
83    }
84
85    #[test]
86    fn test_hash_from_string() {
87        let hash: Hash = "abc123def456".to_string().into();
88        assert_eq!(hash.0, "abc123def456");
89    }
90
91    #[test]
92    fn test_hash_from_str() {
93        let hash: Hash = "abc123def456".into();
94        assert_eq!(hash.0, "abc123def456");
95    }
96
97    #[test]
98    fn test_hash_clone() {
99        let hash1 = Hash("abc123def456".to_string());
100        let hash2 = hash1.clone();
101        assert_eq!(hash1, hash2);
102    }
103
104    #[test]
105    fn test_hash_debug() {
106        let hash = Hash("abc123def456".to_string());
107        let debug_str = format!("{:?}", hash);
108        assert!(debug_str.contains("abc123def456"));
109    }
110
111    #[test]
112    fn test_hash_partial_eq() {
113        let hash1 = Hash("abc123def456".to_string());
114        let hash2 = Hash("abc123def456".to_string());
115        let hash3 = Hash("different".to_string());
116
117        assert_eq!(hash1, hash2);
118        assert_ne!(hash1, hash3);
119    }
120
121    #[test]
122    fn test_hash_from_conversions_edge_cases() {
123        let empty_string: Hash = "".into();
124        assert_eq!(empty_string.0, "");
125
126        let empty_owned: Hash = String::new().into();
127        assert_eq!(empty_owned.0, "");
128
129        let unicode: Hash = "🚀commit".into();
130        assert_eq!(unicode.0, "🚀commit");
131    }
132}