git_prole/git/refs/
local_branch.rs1use std::fmt::Debug;
2use std::fmt::Display;
3use std::ops::Deref;
4use std::str::FromStr;
5
6use miette::miette;
7
8use super::Ref;
9use super::RemoteBranchRef;
10
11#[derive(Clone, Hash, PartialEq, Eq)]
13pub struct LocalBranchRef(Ref);
14
15impl Debug for LocalBranchRef {
16 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17 Debug::fmt(&self.0, f)
18 }
19}
20
21impl PartialEq<Ref> for LocalBranchRef {
22 fn eq(&self, other: &Ref) -> bool {
23 self.0.eq(other)
24 }
25}
26
27impl LocalBranchRef {
28 pub fn new(name: String) -> Self {
29 Self(Ref::new(Ref::HEADS.to_owned(), name))
30 }
31
32 pub fn branch_name(&self) -> &str {
34 self.0.name()
35 }
36
37 pub fn on_remote(&self, remote: &str) -> RemoteBranchRef {
38 RemoteBranchRef::new(remote, self.branch_name())
39 }
40}
41
42impl Deref for LocalBranchRef {
43 type Target = Ref;
44
45 fn deref(&self) -> &Self::Target {
46 &self.0
47 }
48}
49
50impl TryFrom<Ref> for LocalBranchRef {
51 type Error = miette::Report;
52
53 fn try_from(value: Ref) -> Result<Self, Self::Error> {
54 if value.is_local_branch() {
55 Ok(Self(value))
56 } else {
57 Err(miette!("Ref is not a local branch: {value}"))
58 }
59 }
60}
61
62impl FromStr for LocalBranchRef {
63 type Err = miette::Report;
64
65 fn from_str(s: &str) -> Result<Self, Self::Err> {
66 Ref::from_str(s)?.try_into()
67 }
68}
69
70impl<S> From<S> for LocalBranchRef
71where
72 S: AsRef<str>,
73{
74 fn from(value: S) -> Self {
75 Self::new(value.as_ref().to_owned())
76 }
77}
78
79impl Display for LocalBranchRef {
80 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81 Display::fmt(&self.0, f)
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use std::str::FromStr;
88
89 use pretty_assertions::assert_eq;
90
91 use super::*;
92
93 #[test]
94 fn local_branch_ref_try_from() {
95 let branch =
96 LocalBranchRef::try_from(Ref::from_str("refs/heads/puppy/doggy").unwrap()).unwrap();
97
98 assert_eq!(branch.branch_name(), "puppy/doggy");
99 }
100
101 #[test]
102 fn local_branch_ref_from_str() {
103 let branch = LocalBranchRef::from("puppy");
104
105 assert_eq!(branch, Ref::from_str("refs/heads/puppy").unwrap());
106 }
107
108 #[test]
109 fn test_local_branch_new() {
110 assert_eq!(
111 LocalBranchRef::new("puppy".into()),
112 Ref::from_str("refs/heads/puppy").unwrap(),
113 );
114 }
115
116 #[test]
117 fn test_local_branch_branch_name() {
118 assert_eq!(LocalBranchRef::new("puppy".into()).branch_name(), "puppy",);
119 }
120
121 #[test]
122 fn test_local_branch_on_remote() {
123 assert_eq!(
124 LocalBranchRef::new("puppy".into()).on_remote("origin"),
125 Ref::from_str("refs/remotes/origin/puppy").unwrap(),
126 );
127 }
128
129 #[test]
130 fn test_remote_branch_display() {
131 let branch = LocalBranchRef::new("puppy".into());
132 assert_eq!(format!("{branch}"), "puppy");
133 assert_eq!(format!("{branch:#}"), "refs/heads/puppy");
134 }
135}