git_spawn/command/
commit.rs1use crate::command::{CommandExecutor, CommandOutput, GitCommand};
4use crate::error::Result;
5use async_trait::async_trait;
6use std::path::PathBuf;
7
8#[derive(Debug, Clone, Default)]
10pub struct CommitCommand {
11 pub executor: CommandExecutor,
13 pub message: Option<String>,
15 pub message_file: Option<PathBuf>,
17 pub all: bool,
19 pub amend: bool,
21 pub no_edit: bool,
23 pub allow_empty: bool,
25 pub allow_empty_message: bool,
27 pub signoff: bool,
29 pub no_verify: bool,
31 pub author: Option<String>,
33 pub date: Option<String>,
35 pub only_paths: Vec<String>,
37 pub quiet: bool,
39 pub verbose: bool,
41}
42
43impl CommitCommand {
44 #[must_use]
46 pub fn new() -> Self {
47 Self::default()
48 }
49
50 pub fn with_message(msg: impl Into<String>) -> Self {
52 let mut c = Self::new();
53 c.message = Some(msg.into());
54 c
55 }
56
57 pub fn message(&mut self, msg: impl Into<String>) -> &mut Self {
59 self.message = Some(msg.into());
60 self
61 }
62
63 pub fn message_file(&mut self, path: impl Into<PathBuf>) -> &mut Self {
65 self.message_file = Some(path.into());
66 self
67 }
68
69 pub fn all(&mut self) -> &mut Self {
71 self.all = true;
72 self
73 }
74
75 pub fn amend(&mut self) -> &mut Self {
77 self.amend = true;
78 self
79 }
80
81 pub fn no_edit(&mut self) -> &mut Self {
83 self.no_edit = true;
84 self
85 }
86
87 pub fn allow_empty(&mut self) -> &mut Self {
89 self.allow_empty = true;
90 self
91 }
92
93 pub fn allow_empty_message(&mut self) -> &mut Self {
95 self.allow_empty_message = true;
96 self
97 }
98
99 pub fn signoff(&mut self) -> &mut Self {
101 self.signoff = true;
102 self
103 }
104
105 pub fn no_verify(&mut self) -> &mut Self {
107 self.no_verify = true;
108 self
109 }
110
111 pub fn author(&mut self, a: impl Into<String>) -> &mut Self {
113 self.author = Some(a.into());
114 self
115 }
116
117 pub fn date(&mut self, d: impl Into<String>) -> &mut Self {
119 self.date = Some(d.into());
120 self
121 }
122
123 pub fn only(&mut self, path: impl Into<String>) -> &mut Self {
125 self.only_paths.push(path.into());
126 self
127 }
128
129 pub fn quiet(&mut self) -> &mut Self {
131 self.quiet = true;
132 self
133 }
134
135 pub fn verbose(&mut self) -> &mut Self {
137 self.verbose = true;
138 self
139 }
140}
141
142#[async_trait]
143impl GitCommand for CommitCommand {
144 type Output = CommandOutput;
145
146 fn get_executor(&self) -> &CommandExecutor {
147 &self.executor
148 }
149
150 fn get_executor_mut(&mut self) -> &mut CommandExecutor {
151 &mut self.executor
152 }
153
154 fn build_command_args(&self) -> Vec<String> {
155 let mut args = vec!["commit".to_string()];
156 if self.all {
157 args.push("--all".into());
158 }
159 if self.amend {
160 args.push("--amend".into());
161 }
162 if self.no_edit {
163 args.push("--no-edit".into());
164 }
165 if self.allow_empty {
166 args.push("--allow-empty".into());
167 }
168 if self.allow_empty_message {
169 args.push("--allow-empty-message".into());
170 }
171 if self.signoff {
172 args.push("--signoff".into());
173 }
174 if self.no_verify {
175 args.push("--no-verify".into());
176 }
177 if self.quiet {
178 args.push("--quiet".into());
179 }
180 if self.verbose {
181 args.push("--verbose".into());
182 }
183 if let Some(a) = &self.author {
184 args.push(format!("--author={a}"));
185 }
186 if let Some(d) = &self.date {
187 args.push(format!("--date={d}"));
188 }
189 if let Some(m) = &self.message {
190 args.push("-m".into());
191 args.push(m.clone());
192 }
193 if let Some(f) = &self.message_file {
194 args.push("-F".into());
195 args.push(f.display().to_string());
196 }
197 if !self.only_paths.is_empty() {
198 args.push("--only".into());
199 args.push("--".into());
200 args.extend(self.only_paths.iter().cloned());
201 }
202 args
203 }
204
205 async fn execute(&self) -> Result<CommandOutput> {
206 self.execute_raw().await
207 }
208}