docker_wrapper/command/manifest/
rm.rs

1//! Docker manifest rm command implementation.
2
3use crate::command::{CommandExecutor, CommandOutput, DockerCommand};
4use crate::error::Result;
5use async_trait::async_trait;
6
7/// Result of manifest rm command
8#[derive(Debug, Clone)]
9pub struct ManifestRmResult {
10    /// The manifest lists that were removed
11    pub manifest_lists: Vec<String>,
12    /// Raw output from the command
13    pub output: String,
14    /// Whether the command succeeded
15    pub success: bool,
16}
17
18impl ManifestRmResult {
19    /// Parse the manifest rm output
20    fn parse(manifest_lists: &[String], output: &CommandOutput) -> Self {
21        Self {
22            manifest_lists: manifest_lists.to_vec(),
23            output: output.stdout.clone(),
24            success: output.success,
25        }
26    }
27}
28
29/// Docker manifest rm command builder
30///
31/// Deletes one or more manifest lists from local storage.
32///
33/// # Example
34///
35/// ```rust,no_run
36/// use docker_wrapper::{DockerCommand, ManifestRmCommand};
37///
38/// # #[tokio::main]
39/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
40/// let result = ManifestRmCommand::new("myapp:latest")
41///     .execute()
42///     .await?;
43///
44/// println!("Removed {} manifest lists", result.manifest_lists.len());
45/// # Ok(())
46/// # }
47/// ```
48#[derive(Debug, Clone)]
49pub struct ManifestRmCommand {
50    /// The manifest lists to remove
51    manifest_lists: Vec<String>,
52    /// Command executor
53    pub executor: CommandExecutor,
54}
55
56impl ManifestRmCommand {
57    /// Create a new manifest rm command
58    ///
59    /// # Arguments
60    ///
61    /// * `manifest_list` - The manifest list to remove (e.g., "myapp:latest")
62    #[must_use]
63    pub fn new(manifest_list: impl Into<String>) -> Self {
64        Self {
65            manifest_lists: vec![manifest_list.into()],
66            executor: CommandExecutor::new(),
67        }
68    }
69
70    /// Add another manifest list to remove
71    #[must_use]
72    pub fn manifest_list(mut self, manifest_list: impl Into<String>) -> Self {
73        self.manifest_lists.push(manifest_list.into());
74        self
75    }
76
77    /// Add multiple manifest lists to remove
78    #[must_use]
79    pub fn manifest_lists<I, S>(mut self, manifest_lists: I) -> Self
80    where
81        I: IntoIterator<Item = S>,
82        S: Into<String>,
83    {
84        for list in manifest_lists {
85            self.manifest_lists.push(list.into());
86        }
87        self
88    }
89
90    /// Build the command arguments
91    fn build_args(&self) -> Vec<String> {
92        let mut args = vec!["manifest".to_string(), "rm".to_string()];
93
94        for list in &self.manifest_lists {
95            args.push(list.clone());
96        }
97
98        args.extend(self.executor.raw_args.clone());
99
100        args
101    }
102}
103
104#[async_trait]
105impl DockerCommand for ManifestRmCommand {
106    type Output = ManifestRmResult;
107
108    fn get_executor(&self) -> &CommandExecutor {
109        &self.executor
110    }
111
112    fn get_executor_mut(&mut self) -> &mut CommandExecutor {
113        &mut self.executor
114    }
115
116    fn build_command_args(&self) -> Vec<String> {
117        self.build_args()
118    }
119
120    async fn execute(&self) -> Result<Self::Output> {
121        let args = self.build_args();
122        let output = self.execute_command(args).await?;
123        Ok(ManifestRmResult::parse(&self.manifest_lists, &output))
124    }
125}
126
127#[cfg(test)]
128mod tests {
129    use super::*;
130
131    #[test]
132    fn test_manifest_rm_basic() {
133        let cmd = ManifestRmCommand::new("myapp:latest");
134        let args = cmd.build_args();
135        assert_eq!(args, vec!["manifest", "rm", "myapp:latest"]);
136    }
137
138    #[test]
139    fn test_manifest_rm_multiple() {
140        let cmd = ManifestRmCommand::new("myapp:latest").manifest_list("myapp:v1");
141        let args = cmd.build_args();
142        assert_eq!(args, vec!["manifest", "rm", "myapp:latest", "myapp:v1"]);
143    }
144
145    #[test]
146    fn test_manifest_rm_with_manifest_lists() {
147        let cmd =
148            ManifestRmCommand::new("myapp:latest").manifest_lists(vec!["myapp:v1", "myapp:v2"]);
149        let args = cmd.build_args();
150        assert!(args.contains(&"myapp:latest".to_string()));
151        assert!(args.contains(&"myapp:v1".to_string()));
152        assert!(args.contains(&"myapp:v2".to_string()));
153    }
154}