docker_wrapper/compose/
watch.rs1use crate::compose::{ComposeCommandV2 as ComposeCommand, ComposeConfig};
4use crate::error::Result;
5use async_trait::async_trait;
6
7#[derive(Debug, Clone, Default)]
11pub struct ComposeWatchCommand {
12 pub config: ComposeConfig,
14 pub no_up: bool,
16 pub services: Vec<String>,
18}
19
20#[derive(Debug, Clone)]
22pub struct WatchResult {
23 pub output: String,
25 pub success: bool,
27}
28
29impl ComposeWatchCommand {
30 #[must_use]
32 pub fn new() -> Self {
33 Self::default()
34 }
35
36 #[must_use]
38 pub fn file<P: Into<std::path::PathBuf>>(mut self, file: P) -> Self {
39 self.config.files.push(file.into());
40 self
41 }
42
43 #[must_use]
45 pub fn project_name(mut self, name: impl Into<String>) -> Self {
46 self.config.project_name = Some(name.into());
47 self
48 }
49
50 #[must_use]
52 pub fn no_up(mut self) -> Self {
53 self.no_up = true;
54 self
55 }
56
57 #[must_use]
59 pub fn service(mut self, service: impl Into<String>) -> Self {
60 self.services.push(service.into());
61 self
62 }
63
64 #[must_use]
66 pub fn services<I, S>(mut self, services: I) -> Self
67 where
68 I: IntoIterator<Item = S>,
69 S: Into<String>,
70 {
71 self.services.extend(services.into_iter().map(Into::into));
72 self
73 }
74
75 fn build_args(&self) -> Vec<String> {
76 let mut args = vec!["watch".to_string()];
77
78 if self.no_up {
80 args.push("--no-up".to_string());
81 }
82
83 args.extend(self.services.clone());
85
86 args
87 }
88}
89
90#[async_trait]
91impl ComposeCommand for ComposeWatchCommand {
92 type Output = WatchResult;
93
94 fn get_config(&self) -> &ComposeConfig {
95 &self.config
96 }
97
98 fn get_config_mut(&mut self) -> &mut ComposeConfig {
99 &mut self.config
100 }
101
102 async fn execute_compose(&self, args: Vec<String>) -> Result<Self::Output> {
103 let output = self.execute_compose_command(args).await?;
104
105 Ok(WatchResult {
106 output: output.stdout,
107 success: output.success,
108 })
109 }
110
111 async fn execute(&self) -> Result<Self::Output> {
112 let args = self.build_args();
113 self.execute_compose(args).await
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120
121 #[test]
122 fn test_watch_command_basic() {
123 let cmd = ComposeWatchCommand::new();
124 let args = cmd.build_args();
125 assert_eq!(args[0], "watch");
126 }
127
128 #[test]
129 fn test_watch_command_with_no_up() {
130 let cmd = ComposeWatchCommand::new().no_up();
131 let args = cmd.build_args();
132 assert!(args.contains(&"--no-up".to_string()));
133 }
134
135 #[test]
136 fn test_watch_command_with_services() {
137 let cmd = ComposeWatchCommand::new().service("web").service("worker");
138 let args = cmd.build_args();
139 assert!(args.contains(&"web".to_string()));
140 assert!(args.contains(&"worker".to_string()));
141 }
142}