use std::path::PathBuf;
use anyhow::{anyhow, Result};
use blue_build_recipe::Recipe;
use blue_build_template::{ContainerFileTemplate, Template};
use blue_build_utils::constants::*;
use clap::Args;
use log::{debug, info, trace};
use typed_builder::TypedBuilder;
use uuid::Uuid;
use super::BlueBuildCommand;
#[derive(Debug, Clone, Args, TypedBuilder)]
pub struct TemplateCommand {
#[arg()]
#[builder(default, setter(into, strip_option))]
recipe: Option<PathBuf>,
#[arg(short, long)]
#[builder(default, setter(into, strip_option))]
output: Option<PathBuf>,
#[clap(skip)]
#[builder(default, setter(into, strip_option))]
build_id: Option<Uuid>,
}
impl BlueBuildCommand for TemplateCommand {
fn try_run(&mut self) -> Result<()> {
info!(
"Templating for recipe at {}",
self.recipe
.clone()
.unwrap_or_else(|| PathBuf::from(RECIPE_PATH))
.display()
);
self.build_id.get_or_insert(Uuid::new_v4());
self.template_file()
}
}
impl TemplateCommand {
fn template_file(&self) -> Result<()> {
trace!("TemplateCommand::template_file()");
let recipe_path = self
.recipe
.clone()
.unwrap_or_else(|| PathBuf::from(RECIPE_PATH));
debug!("Deserializing recipe");
let recipe_de = Recipe::parse(&recipe_path)?;
trace!("recipe_de: {recipe_de:#?}");
let build_id = self
.build_id
.ok_or_else(|| anyhow!("Build ID should have been generated by now"))?;
let template = ContainerFileTemplate::builder()
.build_id(build_id)
.recipe(&recipe_de)
.recipe_path(recipe_path.as_path())
.build();
let output_str = template.render()?;
if let Some(output) = self.output.as_ref() {
debug!("Templating to file {}", output.display());
trace!("Containerfile:\n{output_str}");
std::fs::write(output, output_str)?;
} else {
debug!("Templating to stdout");
println!("{output_str}");
}
info!("Finished templating Containerfile");
Ok(())
}
}