use anyhow::{anyhow, Result};
use compose_yml::v2 as dc;
use regex::Regex;
use std::env;
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::process;
fn git_to_local(ctx: &dc::Context) -> Result<PathBuf> {
match ctx {
&dc::Context::GitUrl(ref url) => {
let re = Regex::new(r#"/([^./]+)(?:\.git)?"#).unwrap();
match re.captures(url.as_ref()) {
None => Err(anyhow!("Can't get dir name from Git URL: {}", url)),
Some(caps) => {
let path = Path::new(caps.get(1).unwrap().as_str());
Ok(path.to_owned())
}
}
}
&dc::Context::Dir(ref dir) => Ok(dir.clone()),
}
}
fn service_build_dir(service: &dc::Service) -> Result<Option<PathBuf>> {
if let Some(ref build) = service.build {
let mut path = Path::new("src").to_owned();
path.push(git_to_local(build.context.value()?)?);
Ok(Some(path))
} else {
Ok(None)
}
}
fn update(file: &mut dc::File) -> Result<()> {
for (_name, service) in file.services.iter_mut() {
service.env_files.insert(0, dc::escape("pods/common.env")?);
service
.env_files
.insert(1, dc::raw("pods/overrides/$ENV/common.env")?);
let build_dir = service_build_dir(service)?;
if let Some(ref dir) = build_dir {
service
.volumes
.push(dc::value(dc::VolumeMount::host(dir, "/app")));
if let Some(ref mut build) = service.build {
build.context = dc::value(dc::Context::Dir(dir.clone()));
}
}
}
Ok(())
}
fn run() -> Result<()> {
let args: Vec<_> = env::args().collect();
if args.len() != 3 {
return Err(anyhow!("Usage: miniconductor <infile> <outfile>"));
}
let in_path = Path::new(&args[1]);
let out_path = Path::new(&args[2]);
let mut file = dc::File::read_from_path(in_path)?;
update(&mut file)?;
file.write_to_path(out_path)?;
Ok(())
}
fn main() {
if let Err(ref err) = run() {
write!(io::stderr(), "Error: {}", err).unwrap();
process::exit(1);
}
}