git_spawn/command/
symbolic_ref.rs1use crate::command::{CommandExecutor, GitCommand};
4use crate::error::{Error, Result};
5use async_trait::async_trait;
6
7#[derive(Debug, Clone)]
9pub enum SymbolicRefAction {
10 Read {
12 name: String,
14 short: bool,
16 },
17 Set {
19 name: String,
21 target: String,
23 reason: Option<String>,
25 },
26 Delete {
28 name: String,
30 quiet: bool,
32 },
33}
34
35#[derive(Debug, Clone)]
37pub struct SymbolicRefCommand {
38 pub executor: CommandExecutor,
40 pub action: SymbolicRefAction,
42}
43
44impl SymbolicRefCommand {
45 pub fn read(name: impl Into<String>) -> Self {
47 Self {
48 executor: CommandExecutor::default(),
49 action: SymbolicRefAction::Read {
50 name: name.into(),
51 short: false,
52 },
53 }
54 }
55
56 #[must_use]
58 pub fn short(mut self) -> Self {
59 if let SymbolicRefAction::Read { short, .. } = &mut self.action {
60 *short = true;
61 }
62 self
63 }
64
65 pub fn set(name: impl Into<String>, target: impl Into<String>) -> Self {
67 Self {
68 executor: CommandExecutor::default(),
69 action: SymbolicRefAction::Set {
70 name: name.into(),
71 target: target.into(),
72 reason: None,
73 },
74 }
75 }
76
77 #[must_use]
79 pub fn reason(mut self, r: impl Into<String>) -> Self {
80 if let SymbolicRefAction::Set { reason, .. } = &mut self.action {
81 *reason = Some(r.into());
82 }
83 self
84 }
85
86 pub fn delete(name: impl Into<String>) -> Self {
88 Self {
89 executor: CommandExecutor::default(),
90 action: SymbolicRefAction::Delete {
91 name: name.into(),
92 quiet: false,
93 },
94 }
95 }
96
97 #[must_use]
99 pub fn quiet(mut self) -> Self {
100 if let SymbolicRefAction::Delete { quiet, .. } = &mut self.action {
101 *quiet = true;
102 }
103 self
104 }
105}
106
107#[async_trait]
108impl GitCommand for SymbolicRefCommand {
109 type Output = String;
111
112 fn get_executor(&self) -> &CommandExecutor {
113 &self.executor
114 }
115
116 fn get_executor_mut(&mut self) -> &mut CommandExecutor {
117 &mut self.executor
118 }
119
120 fn build_command_args(&self) -> Vec<String> {
121 let mut args = vec!["symbolic-ref".to_string()];
122 match &self.action {
123 SymbolicRefAction::Read { name, short } => {
124 if *short {
125 args.push("--short".into());
126 }
127 args.push(name.clone());
128 }
129 SymbolicRefAction::Set {
130 name,
131 target,
132 reason,
133 } => {
134 if let Some(r) = reason {
135 args.push("-m".into());
136 args.push(r.clone());
137 }
138 args.push(name.clone());
139 args.push(target.clone());
140 }
141 SymbolicRefAction::Delete { name, quiet } => {
142 args.push("--delete".into());
143 if *quiet {
144 args.push("-q".into());
145 }
146 args.push(name.clone());
147 }
148 }
149 args
150 }
151
152 async fn execute(&self) -> Result<String> {
153 if let SymbolicRefAction::Read { name, .. } | SymbolicRefAction::Set { name, .. } =
154 &self.action
155 {
156 if name.is_empty() {
157 return Err(Error::invalid_config("symbolic-ref requires a ref name"));
158 }
159 }
160 let out = self.execute_raw().await?;
161 Ok(out.stdout_trimmed().to_string())
162 }
163}