use super::{CommandExecutor, CommandOutput, DockerCommand};
use crate::error::Result;
use async_trait::async_trait;
use std::fmt;
#[derive(Debug, Clone)]
pub struct InitCommand {
show_version: bool,
pub executor: CommandExecutor,
}
#[derive(Debug, Clone, PartialEq)]
pub enum InitTemplate {
AspNetCore,
Go,
Java,
Node,
Php,
Python,
Rust,
Other,
}
#[derive(Debug, Clone)]
pub struct InitOutput {
pub output: CommandOutput,
pub version_requested: bool,
}
impl InitCommand {
#[must_use]
pub fn new() -> Self {
Self {
show_version: false,
executor: CommandExecutor::new(),
}
}
#[must_use]
pub fn version(mut self) -> Self {
self.show_version = true;
self
}
#[must_use]
pub fn is_version(&self) -> bool {
self.show_version
}
}
impl Default for InitCommand {
fn default() -> Self {
Self::new()
}
}
#[async_trait]
impl DockerCommand for InitCommand {
type Output = InitOutput;
fn get_executor(&self) -> &CommandExecutor {
&self.executor
}
fn get_executor_mut(&mut self) -> &mut CommandExecutor {
&mut self.executor
}
fn build_command_args(&self) -> Vec<String> {
let mut args = vec!["init".to_string()];
if self.show_version {
args.push("--version".to_string());
}
args.extend(self.executor.raw_args.clone());
args
}
async fn execute(&self) -> Result<Self::Output> {
let args = self.build_command_args();
let output = self.execute_command(args).await?;
Ok(InitOutput {
output,
version_requested: self.show_version,
})
}
}
impl InitOutput {
#[must_use]
pub fn success(&self) -> bool {
self.output.success
}
#[must_use]
pub fn version(&self) -> Option<&str> {
if self.version_requested && self.success() {
Some(self.output.stdout.trim())
} else {
None
}
}
#[must_use]
pub fn is_version_output(&self) -> bool {
self.version_requested
}
#[must_use]
pub fn files_created(&self) -> bool {
!self.version_requested && self.success()
}
#[must_use]
pub fn stdout(&self) -> &str {
&self.output.stdout
}
#[must_use]
pub fn stderr(&self) -> &str {
&self.output.stderr
}
}
impl fmt::Display for InitCommand {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "docker init")?;
if self.show_version {
write!(f, " --version")?;
}
Ok(())
}
}
impl fmt::Display for InitTemplate {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let name = match self {
Self::AspNetCore => "ASP.NET Core",
Self::Go => "Go",
Self::Java => "Java",
Self::Node => "Node",
Self::Php => "PHP with Apache",
Self::Python => "Python",
Self::Rust => "Rust",
Self::Other => "Other",
};
write!(f, "{name}")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_init_command_basic() {
let cmd = InitCommand::new();
assert!(!cmd.is_version());
let args = cmd.build_command_args();
assert_eq!(args, vec!["init"]);
}
#[test]
fn test_init_command_version() {
let cmd = InitCommand::new().version();
assert!(cmd.is_version());
let args = cmd.build_command_args();
assert_eq!(args, vec!["init", "--version"]);
}
#[test]
fn test_init_command_default() {
let cmd = InitCommand::default();
assert!(!cmd.is_version());
let args = cmd.build_command_args();
assert_eq!(args, vec!["init"]);
}
#[test]
fn test_init_command_display() {
let cmd = InitCommand::new();
assert_eq!(format!("{cmd}"), "docker init");
let cmd_version = InitCommand::new().version();
assert_eq!(format!("{cmd_version}"), "docker init --version");
}
#[test]
fn test_init_template_display() {
assert_eq!(format!("{}", InitTemplate::AspNetCore), "ASP.NET Core");
assert_eq!(format!("{}", InitTemplate::Go), "Go");
assert_eq!(format!("{}", InitTemplate::Java), "Java");
assert_eq!(format!("{}", InitTemplate::Node), "Node");
assert_eq!(format!("{}", InitTemplate::Php), "PHP with Apache");
assert_eq!(format!("{}", InitTemplate::Python), "Python");
assert_eq!(format!("{}", InitTemplate::Rust), "Rust");
assert_eq!(format!("{}", InitTemplate::Other), "Other");
}
#[test]
fn test_init_output_helpers() {
let output = InitOutput {
output: CommandOutput {
stdout: "Version: v1.4.0".to_string(),
stderr: String::new(),
exit_code: 0,
success: true,
},
version_requested: true,
};
assert!(output.success());
assert!(output.is_version_output());
assert!(!output.files_created());
assert_eq!(output.version(), Some("Version: v1.4.0"));
assert_eq!(output.stdout(), "Version: v1.4.0");
}
#[test]
fn test_init_output_files_created() {
let output = InitOutput {
output: CommandOutput {
stdout: "Files created successfully".to_string(),
stderr: String::new(),
exit_code: 0,
success: true,
},
version_requested: false,
};
assert!(output.success());
assert!(!output.is_version_output());
assert!(output.files_created());
assert_eq!(output.version(), None);
}
#[test]
fn test_init_command_extensibility() {
let mut cmd = InitCommand::new();
cmd.get_executor_mut()
.raw_args
.push("--custom-flag".to_string());
let args = cmd.build_command_args();
assert!(args.contains(&"--custom-flag".to_string()));
}
}