use clap::Parser;
use colored::*;
use std::{fs, process};
use docker_pose::{
cmd_get_success_output_or_fail, get_and_save, get_service, get_slug, get_yml_content,
print_names, unwrap_filter_regex, unwrap_filter_tag, Args, Commands, ComposeYaml,
DockerCommand, GitCommand, Objects, ReplaceTag, Verbosity,
};
fn main() {
setup_terminal();
let args = Args::parse();
let verbosity = args.get_verbosity();
if let Commands::Slug { text } = args.command {
if let Some(t) = text {
println!("{}", get_slug(&t));
} else {
let command = GitCommand::new(verbosity.clone());
let result_output = command.get_current_branch();
match result_output {
Ok(output) => {
let slug = cmd_get_success_output_or_fail(
&command.git_bin,
"rev-parse",
output,
args.quiet,
);
println!("{}", get_slug(&slug));
}
Err(e) => {
eprintln!("{}: calling git: {}", "ERROR".red(), e);
process::exit(21);
}
}
}
process::exit(0)
} else if let Commands::Get {
url,
script,
output,
timeout_connect,
max_time,
headers,
} = args.command
{
get_and_save(
&url,
&script,
&output,
timeout_connect,
max_time,
&headers,
verbosity.clone(),
);
process::exit(0)
}
if args.filenames.len() > 1 && args.no_docker {
eprintln!(
"{}: multiple '{}' arguments cannot be used with '{}'",
"ERROR".red(),
"--file".yellow(),
"--no-docker".yellow()
);
process::exit(2);
}
let yaml_content = match args.no_docker {
true => get_yml_content(args.filenames.first().map(AsRef::as_ref), verbosity.clone()),
false => {
let command = DockerCommand::new(verbosity.clone());
let result_output = command.call_compose_config(
&args.filenames.iter().map(AsRef::as_ref).collect::<Vec<_>>(),
args.no_consistency,
false,
false,
);
match result_output {
Ok(output) => {
cmd_get_success_output_or_fail(
&command.docker_bin,
"compose",
output,
args.quiet,
)
}
Err(e) => {
eprintln!("{}: calling compose: {}", "ERROR".red(), e);
eprintln!(
"{}: parsing will be executed without compose",
"WARN".yellow()
);
get_yml_content(args.filenames.first().map(AsRef::as_ref), verbosity.clone())
}
}
}
};
let mut compose = ComposeYaml::new(&yaml_content).unwrap_or_else(|err| {
if err.to_string().starts_with("invalid type") {
eprintln!(
"{}: parsing compose YAML file: invalid content",
"ERROR".red()
);
process::exit(13);
}
eprintln!("{}: parsing YAML file: {}", "ERROR".red(), err);
process::exit(15);
});
match args.command {
Commands::List { object, pretty } => match object {
Objects::Envs { service } => {
let serv = get_service(&compose, &service);
let envs_op = compose.get_service_envs(serv);
if let Some(envs) = envs_op {
envs.iter().for_each(|env| println!("{}", env));
}
}
Objects::Depends { service } => {
let serv = get_service(&compose, &service);
let deps_op = compose.get_service_depends_on(serv);
if let Some(envs) = deps_op {
envs.iter().for_each(|env| println!("{}", env));
}
}
Objects::Profiles => {
let op = compose.get_profiles_names();
match op {
None => {
eprintln!("{}: No profiles section found", "ERROR".red());
process::exit(15);
}
Some(profiles) => {
print_names(profiles.into_iter(), pretty);
}
}
}
Objects::Images {
filter,
tag,
tag_filter,
ignore_unauthorized,
progress,
no_slug,
offline,
threads,
} => {
let regex = unwrap_filter_regex(tag_filter.as_deref());
let replace_tag = tag.map(|tag| ReplaceTag {
tag,
ignore_unauthorized,
threads,
no_slug,
offline,
tag_filter: regex,
verbosity: verbosity.clone(),
progress_verbosity: match progress {
true => Verbosity::Verbose,
false => Verbosity::Quiet,
},
});
let filter_by_tag = unwrap_filter_tag(filter.as_deref());
let op = compose.get_images(filter_by_tag, replace_tag.as_ref());
match op {
None => {
eprintln!("{}: No services section found", "ERROR".red());
process::exit(15);
}
Some(images) => {
let images_list = images.iter().map(|i| i.as_str()).collect::<Vec<_>>();
print_names(images_list.into_iter(), pretty);
}
}
}
Objects::Services
| Objects::Volumes
| Objects::Networks
| Objects::Configs
| Objects::Secrets => {
let root_element = object.to_string().to_lowercase();
let el_iter = compose.get_root_element_names(&root_element).into_iter();
print_names(el_iter, pretty);
}
},
Commands::Config {
output,
tag,
tag_filter,
ignore_unauthorized,
progress,
no_slug,
offline,
threads,
} => {
let regex = unwrap_filter_regex(tag_filter.as_deref());
let replace_tag = tag.map(|tag| ReplaceTag {
tag,
ignore_unauthorized,
offline,
threads,
no_slug,
tag_filter: regex,
verbosity: verbosity.clone(),
progress_verbosity: match progress {
true => Verbosity::Verbose,
false => Verbosity::Quiet,
},
});
if let Some(remote_t) = replace_tag {
compose.update_images_tag(&remote_t);
}
let result = compose.to_string().unwrap_or_else(|err| {
eprintln!("{}: {}", "ERROR".red(), err);
process::exit(20);
});
if let Some(file) = output {
fs::write(&file, result).unwrap_or_else(|e| {
eprintln!(
"{}: writing output to '{}' file: {}",
"ERROR".red(),
file.yellow(),
e
);
process::exit(18);
});
} else {
println!("{}", result);
}
}
Commands::Slug { .. } | Commands::Get { .. } => {
}
}
}
#[cfg(target_os = "windows")]
fn setup_terminal() {
control::set_virtual_terminal(true).unwrap();
}
#[cfg(not(target_os = "windows"))]
fn setup_terminal() {
}