docker_wrapper/compose/
version.rs1use crate::compose::{ComposeCommandV2 as ComposeCommand, ComposeConfig};
4use crate::error::Result;
5use async_trait::async_trait;
6use serde::Deserialize;
7
8#[derive(Debug, Clone, Default)]
12pub struct ComposeVersionCommand {
13 pub config: ComposeConfig,
15 pub format: Option<VersionFormat>,
17 pub short: bool,
19}
20
21#[derive(Debug, Clone, Copy)]
23pub enum VersionFormat {
24 Pretty,
26 Json,
28}
29
30impl VersionFormat {
31 #[must_use]
33 pub fn as_arg(&self) -> &str {
34 match self {
35 Self::Pretty => "pretty",
36 Self::Json => "json",
37 }
38 }
39}
40
41#[derive(Debug, Clone, Deserialize)]
43#[serde(rename_all = "PascalCase")]
44pub struct VersionInfo {
45 pub version: String,
47}
48
49#[derive(Debug, Clone)]
51pub struct VersionResult {
52 pub info: Option<VersionInfo>,
54 pub raw_output: String,
56}
57
58impl ComposeVersionCommand {
59 #[must_use]
61 pub fn new() -> Self {
62 Self::default()
63 }
64
65 #[must_use]
67 pub fn format(mut self, format: VersionFormat) -> Self {
68 self.format = Some(format);
69 self
70 }
71
72 #[must_use]
74 pub fn format_json(mut self) -> Self {
75 self.format = Some(VersionFormat::Json);
76 self
77 }
78
79 #[must_use]
81 pub fn short(mut self) -> Self {
82 self.short = true;
83 self
84 }
85
86 fn build_args(&self) -> Vec<String> {
87 let mut args = vec!["version".to_string()];
88
89 if self.short {
91 args.push("--short".to_string());
92 }
93
94 if let Some(format) = &self.format {
96 args.push("--format".to_string());
97 args.push(format.as_arg().to_string());
98 }
99
100 args
101 }
102}
103
104#[async_trait]
105impl ComposeCommand for ComposeVersionCommand {
106 type Output = VersionResult;
107
108 fn get_config(&self) -> &ComposeConfig {
109 &self.config
110 }
111
112 fn get_config_mut(&mut self) -> &mut ComposeConfig {
113 &mut self.config
114 }
115
116 async fn execute_compose(&self, args: Vec<String>) -> Result<Self::Output> {
117 let output = self.execute_compose_command(args).await?;
118
119 let info = if matches!(self.format, Some(VersionFormat::Json)) {
121 serde_json::from_str(&output.stdout).ok()
122 } else {
123 None
124 };
125
126 Ok(VersionResult {
127 info,
128 raw_output: output.stdout,
129 })
130 }
131
132 async fn execute(&self) -> Result<Self::Output> {
133 let args = self.build_args();
134 self.execute_compose(args).await
135 }
136}
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141
142 #[test]
143 fn test_version_command_basic() {
144 let cmd = ComposeVersionCommand::new();
145 let args = cmd.build_args();
146 assert_eq!(args[0], "version");
147 }
148
149 #[test]
150 fn test_version_command_with_format() {
151 let cmd = ComposeVersionCommand::new().format_json();
152 let args = cmd.build_args();
153 assert!(args.contains(&"--format".to_string()));
154 assert!(args.contains(&"json".to_string()));
155 }
156
157 #[test]
158 fn test_version_command_with_short() {
159 let cmd = ComposeVersionCommand::new().short();
160 let args = cmd.build_args();
161 assert!(args.contains(&"--short".to_string()));
162 }
163}