use super::environment::{
ComposeCommandType, detect_compose_command_type, get_compose_command_type,
set_compose_command_type,
};
use super::types::DockerManager;
use anyhow::Result;
use std::process::Stdio;
use tokio::process::Command;
use tracing::debug;
impl DockerManager {
pub(crate) async fn run_compose_command(&self, args: &[&str]) -> Result<std::process::Output> {
debug!("Running docker-compose command: {:?}", args);
let compose_type = get_compose_command_type();
match compose_type {
ComposeCommandType::DockerComposeSubcommand => {
debug!("Using detected docker compose subcommand");
self.run_docker_compose_subcommand_direct(args).await
}
ComposeCommandType::DockerComposeStandalone => {
debug!("Using detected standalone docker-compose command");
self.run_docker_compose_standalone(args).await
}
ComposeCommandType::Unknown => {
debug!("Compose command type not detected; probing availability first");
self.run_compose_command_with_detection(args).await
}
}
}
async fn run_compose_command_with_detection(
&self,
args: &[&str],
) -> Result<std::process::Output> {
let mut compose_type = get_compose_command_type();
if compose_type == ComposeCommandType::Unknown {
compose_type = detect_compose_command_type().await;
if compose_type != ComposeCommandType::Unknown {
set_compose_command_type(compose_type);
}
} else {
debug!(
"Compose command type was already initialized by another call: {:?}",
compose_type
);
}
match compose_type {
ComposeCommandType::DockerComposeSubcommand => {
debug!("Executing via docker compose subcommand");
self.run_docker_compose_subcommand_direct(args).await
}
ComposeCommandType::DockerComposeStandalone => {
debug!("Executing via standalone docker-compose command");
self.run_docker_compose_standalone(args).await
}
ComposeCommandType::Unknown => {
Err(anyhow::anyhow!(
"No available Docker Compose command found; make sure Docker Compose is installed"
))
}
}
}
async fn run_docker_compose_subcommand_direct(
&self,
args: &[&str],
) -> Result<std::process::Output> {
let compose_path = self.compose_file.to_string_lossy().to_string();
let mut cmd_args = vec!["compose"];
if let Some(ref project_name) = self.project_name {
cmd_args.extend(&["-p", project_name]);
}
cmd_args.extend(&["-f", &compose_path]);
cmd_args.extend(args);
debug!("Executing docker compose subcommand: {:?}", cmd_args);
self.run_docker_command(&cmd_args).await
}
async fn run_docker_compose_standalone(&self, args: &[&str]) -> Result<std::process::Output> {
let compose_path = self.compose_file.to_string_lossy().to_string();
let mut cmd_args: Vec<&str> = vec![];
if let Some(ref project_name) = self.project_name {
cmd_args.extend(&["-p", project_name]);
}
cmd_args.extend(&["-f", &compose_path]);
cmd_args.extend(args);
debug!("Executing standalone docker-compose command: {:?}", cmd_args);
let output = Command::new("docker-compose")
.args(&cmd_args)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.output()
.await?;
Ok(output)
}
pub(crate) async fn run_docker_command(&self, args: &[&str]) -> Result<std::process::Output> {
debug!("Executing docker command: {:?}", args);
let output = Command::new("docker")
.args(args)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.output()
.await?;
Ok(output)
}
}