1use git_hash::ObjectId;
2
3use crate::{FullName, Target};
4
5#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
7#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
8pub struct Reference {
9 pub name: FullName,
11 pub target: Target,
13 pub peeled: Option<ObjectId>,
15}
16
17mod convert {
18 use git_hash::ObjectId;
19
20 use crate::{
21 raw::Reference,
22 store_impl::{file::loose, packed},
23 Target,
24 };
25
26 impl From<Reference> for loose::Reference {
27 fn from(value: Reference) -> Self {
28 loose::Reference {
29 name: value.name,
30 target: value.target,
31 }
32 }
33 }
34
35 impl From<loose::Reference> for Reference {
36 fn from(value: loose::Reference) -> Self {
37 Reference {
38 name: value.name,
39 target: value.target,
40 peeled: None,
41 }
42 }
43 }
44
45 impl<'p> From<packed::Reference<'p>> for Reference {
46 fn from(value: packed::Reference<'p>) -> Self {
47 Reference {
48 name: value.name.into(),
49 target: Target::Peeled(value.target()),
50 peeled: value
51 .object
52 .map(|hex| ObjectId::from_hex(hex).expect("parser validation")),
53 }
54 }
55 }
56}
57
58mod access {
59 use git_object::bstr::ByteSlice;
60
61 use crate::{raw::Reference, FullNameRef, Namespace, Target};
62
63 impl Reference {
64 pub fn kind(&self) -> crate::Kind {
66 self.target.kind()
67 }
68
69 pub fn name_without_namespace(&self, namespace: &Namespace) -> Option<&FullNameRef> {
73 self.name
74 .0
75 .as_bstr()
76 .strip_prefix(namespace.0.as_bstr().as_ref())
77 .map(|stripped| FullNameRef::new_unchecked(stripped.as_bstr()))
78 }
79
80 pub fn strip_namespace(&mut self, namespace: &Namespace) -> &mut Self {
82 self.name.strip_namespace(namespace);
83 if let Target::Symbolic(name) = &mut self.target {
84 name.strip_namespace(namespace);
85 }
86 self
87 }
88 }
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94
95 #[test]
96 fn size_of_reference() {
97 assert_eq!(
98 std::mem::size_of::<Reference>(),
99 80,
100 "let's not let it change size undetected"
101 );
102 }
103}