docker_wrapper/command/
init.rs1use super::{CommandExecutor, CommandOutput, DockerCommand};
8use crate::error::Result;
9use async_trait::async_trait;
10use std::fmt;
11
12#[derive(Debug, Clone)]
37pub struct InitCommand {
38 show_version: bool,
40 pub executor: CommandExecutor,
42}
43
44#[derive(Debug, Clone, PartialEq)]
46pub enum InitTemplate {
47 AspNetCore,
49 Go,
51 Java,
53 Node,
55 Php,
57 Python,
59 Rust,
61 Other,
63}
64
65#[derive(Debug, Clone)]
67pub struct InitOutput {
68 pub output: CommandOutput,
70 pub version_requested: bool,
72}
73
74impl InitCommand {
75 #[must_use]
85 pub fn new() -> Self {
86 Self {
87 show_version: false,
88 executor: CommandExecutor::new(),
89 }
90 }
91
92 #[must_use]
102 pub fn version(mut self) -> Self {
103 self.show_version = true;
104 self
105 }
106
107 #[must_use]
109 pub fn is_version(&self) -> bool {
110 self.show_version
111 }
112}
113
114impl Default for InitCommand {
115 fn default() -> Self {
116 Self::new()
117 }
118}
119
120#[async_trait]
121impl DockerCommand for InitCommand {
122 type Output = InitOutput;
123
124 fn get_executor(&self) -> &CommandExecutor {
125 &self.executor
126 }
127
128 fn get_executor_mut(&mut self) -> &mut CommandExecutor {
129 &mut self.executor
130 }
131
132 fn build_command_args(&self) -> Vec<String> {
133 let mut args = vec!["init".to_string()];
134
135 if self.show_version {
136 args.push("--version".to_string());
137 }
138
139 args.extend(self.executor.raw_args.clone());
141
142 args
143 }
144
145 async fn execute(&self) -> Result<Self::Output> {
146 let args = self.build_command_args();
147 let output = self.execute_command(args).await?;
148
149 Ok(InitOutput {
150 output,
151 version_requested: self.show_version,
152 })
153 }
154}
155
156impl InitOutput {
157 #[must_use]
159 pub fn success(&self) -> bool {
160 self.output.success
161 }
162
163 #[must_use]
165 pub fn version(&self) -> Option<&str> {
166 if self.version_requested && self.success() {
167 Some(self.output.stdout.trim())
168 } else {
169 None
170 }
171 }
172
173 #[must_use]
175 pub fn is_version_output(&self) -> bool {
176 self.version_requested
177 }
178
179 #[must_use]
181 pub fn files_created(&self) -> bool {
182 !self.version_requested && self.success()
183 }
184
185 #[must_use]
187 pub fn stdout(&self) -> &str {
188 &self.output.stdout
189 }
190
191 #[must_use]
193 pub fn stderr(&self) -> &str {
194 &self.output.stderr
195 }
196}
197
198impl fmt::Display for InitCommand {
199 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
200 write!(f, "docker init")?;
201
202 if self.show_version {
203 write!(f, " --version")?;
204 }
205
206 Ok(())
207 }
208}
209
210impl fmt::Display for InitTemplate {
211 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
212 let name = match self {
213 Self::AspNetCore => "ASP.NET Core",
214 Self::Go => "Go",
215 Self::Java => "Java",
216 Self::Node => "Node",
217 Self::Php => "PHP with Apache",
218 Self::Python => "Python",
219 Self::Rust => "Rust",
220 Self::Other => "Other",
221 };
222 write!(f, "{name}")
223 }
224}
225
226#[cfg(test)]
227mod tests {
228 use super::*;
229
230 #[test]
231 fn test_init_command_basic() {
232 let cmd = InitCommand::new();
233 assert!(!cmd.is_version());
234
235 let args = cmd.build_command_args();
236 assert_eq!(args, vec!["init"]);
237 }
238
239 #[test]
240 fn test_init_command_version() {
241 let cmd = InitCommand::new().version();
242 assert!(cmd.is_version());
243
244 let args = cmd.build_command_args();
245 assert_eq!(args, vec!["init", "--version"]);
246 }
247
248 #[test]
249 fn test_init_command_default() {
250 let cmd = InitCommand::default();
251 assert!(!cmd.is_version());
252
253 let args = cmd.build_command_args();
254 assert_eq!(args, vec!["init"]);
255 }
256
257 #[test]
258 fn test_init_command_display() {
259 let cmd = InitCommand::new();
260 assert_eq!(format!("{cmd}"), "docker init");
261
262 let cmd_version = InitCommand::new().version();
263 assert_eq!(format!("{cmd_version}"), "docker init --version");
264 }
265
266 #[test]
267 fn test_init_template_display() {
268 assert_eq!(format!("{}", InitTemplate::AspNetCore), "ASP.NET Core");
269 assert_eq!(format!("{}", InitTemplate::Go), "Go");
270 assert_eq!(format!("{}", InitTemplate::Java), "Java");
271 assert_eq!(format!("{}", InitTemplate::Node), "Node");
272 assert_eq!(format!("{}", InitTemplate::Php), "PHP with Apache");
273 assert_eq!(format!("{}", InitTemplate::Python), "Python");
274 assert_eq!(format!("{}", InitTemplate::Rust), "Rust");
275 assert_eq!(format!("{}", InitTemplate::Other), "Other");
276 }
277
278 #[test]
279 fn test_init_output_helpers() {
280 let output = InitOutput {
281 output: CommandOutput {
282 stdout: "Version: v1.4.0".to_string(),
283 stderr: String::new(),
284 exit_code: 0,
285 success: true,
286 },
287 version_requested: true,
288 };
289
290 assert!(output.success());
291 assert!(output.is_version_output());
292 assert!(!output.files_created());
293 assert_eq!(output.version(), Some("Version: v1.4.0"));
294 assert_eq!(output.stdout(), "Version: v1.4.0");
295 }
296
297 #[test]
298 fn test_init_output_files_created() {
299 let output = InitOutput {
300 output: CommandOutput {
301 stdout: "Files created successfully".to_string(),
302 stderr: String::new(),
303 exit_code: 0,
304 success: true,
305 },
306 version_requested: false,
307 };
308
309 assert!(output.success());
310 assert!(!output.is_version_output());
311 assert!(output.files_created());
312 assert_eq!(output.version(), None);
313 }
314
315 #[test]
316 fn test_init_command_extensibility() {
317 let mut cmd = InitCommand::new();
318
319 cmd.get_executor_mut()
321 .raw_args
322 .push("--custom-flag".to_string());
323
324 let args = cmd.build_command_args();
325 assert!(args.contains(&"--custom-flag".to_string()));
326 }
327}