git_spawn/command/
grep.rs1use crate::command::{CommandExecutor, CommandOutput, GitCommand};
4use crate::error::{Error, Result};
5use async_trait::async_trait;
6
7#[derive(Debug, Clone, Default)]
9pub struct GrepCommand {
10 pub executor: CommandExecutor,
12 pub pattern: Option<String>,
14 pub trees: Vec<String>,
16 pub paths: Vec<String>,
18 pub ignore_case: bool,
20 pub word_regexp: bool,
22 pub invert: bool,
24 pub line_number: bool,
26 pub count: bool,
28 pub files_with_matches: bool,
30 pub files_without_match: bool,
32 pub name_only: bool,
34 pub extended_regexp: bool,
36 pub fixed_strings: bool,
38 pub perl_regexp: bool,
40 pub cached: bool,
42 pub untracked: bool,
44 pub no_index: bool,
46 pub recurse_submodules: bool,
48}
49
50impl GrepCommand {
51 pub fn new(pattern: impl Into<String>) -> Self {
53 Self {
54 pattern: Some(pattern.into()),
55 ..Self::default()
56 }
57 }
58
59 pub fn tree(&mut self, t: impl Into<String>) -> &mut Self {
61 self.trees.push(t.into());
62 self
63 }
64
65 pub fn path(&mut self, p: impl Into<String>) -> &mut Self {
67 self.paths.push(p.into());
68 self
69 }
70
71 pub fn ignore_case(&mut self) -> &mut Self {
73 self.ignore_case = true;
74 self
75 }
76
77 pub fn word_regexp(&mut self) -> &mut Self {
79 self.word_regexp = true;
80 self
81 }
82
83 pub fn invert(&mut self) -> &mut Self {
85 self.invert = true;
86 self
87 }
88
89 pub fn line_number(&mut self) -> &mut Self {
91 self.line_number = true;
92 self
93 }
94
95 pub fn count(&mut self) -> &mut Self {
97 self.count = true;
98 self
99 }
100
101 pub fn files_with_matches(&mut self) -> &mut Self {
103 self.files_with_matches = true;
104 self
105 }
106
107 pub fn files_without_match(&mut self) -> &mut Self {
109 self.files_without_match = true;
110 self
111 }
112
113 pub fn name_only(&mut self) -> &mut Self {
115 self.name_only = true;
116 self
117 }
118
119 pub fn extended_regexp(&mut self) -> &mut Self {
121 self.extended_regexp = true;
122 self
123 }
124
125 pub fn fixed_strings(&mut self) -> &mut Self {
127 self.fixed_strings = true;
128 self
129 }
130
131 pub fn perl_regexp(&mut self) -> &mut Self {
133 self.perl_regexp = true;
134 self
135 }
136
137 pub fn cached(&mut self) -> &mut Self {
139 self.cached = true;
140 self
141 }
142
143 pub fn untracked(&mut self) -> &mut Self {
145 self.untracked = true;
146 self
147 }
148
149 pub fn no_index(&mut self) -> &mut Self {
151 self.no_index = true;
152 self
153 }
154
155 pub fn recurse_submodules(&mut self) -> &mut Self {
157 self.recurse_submodules = true;
158 self
159 }
160}
161
162#[async_trait]
163impl GitCommand for GrepCommand {
164 type Output = CommandOutput;
165 fn get_executor(&self) -> &CommandExecutor {
166 &self.executor
167 }
168 fn get_executor_mut(&mut self) -> &mut CommandExecutor {
169 &mut self.executor
170 }
171 fn build_command_args(&self) -> Vec<String> {
172 let mut args = vec!["grep".to_string()];
173 if self.ignore_case {
174 args.push("-i".into());
175 }
176 if self.word_regexp {
177 args.push("-w".into());
178 }
179 if self.invert {
180 args.push("-v".into());
181 }
182 if self.line_number {
183 args.push("-n".into());
184 }
185 if self.count {
186 args.push("-c".into());
187 }
188 if self.files_with_matches {
189 args.push("-l".into());
190 }
191 if self.files_without_match {
192 args.push("-L".into());
193 }
194 if self.name_only {
195 args.push("--name-only".into());
196 }
197 if self.extended_regexp {
198 args.push("-E".into());
199 }
200 if self.fixed_strings {
201 args.push("-F".into());
202 }
203 if self.perl_regexp {
204 args.push("-P".into());
205 }
206 if self.cached {
207 args.push("--cached".into());
208 }
209 if self.untracked {
210 args.push("--untracked".into());
211 }
212 if self.no_index {
213 args.push("--no-index".into());
214 }
215 if self.recurse_submodules {
216 args.push("--recurse-submodules".into());
217 }
218 if let Some(p) = &self.pattern {
219 args.push("-e".into());
220 args.push(p.clone());
221 }
222 args.extend(self.trees.iter().cloned());
223 if !self.paths.is_empty() {
224 args.push("--".into());
225 args.extend(self.paths.iter().cloned());
226 }
227 args
228 }
229 async fn execute(&self) -> Result<CommandOutput> {
230 if self.pattern.is_none() {
231 return Err(Error::invalid_config("grep requires a pattern"));
232 }
233 self.execute_raw().await
236 }
237}