use std::io::{self, Write};
use std::path::PathBuf;
use anyhow::{Context, Result};
use clap::Parser;
use crate::io::FileOps;
use crate::{Renderer, Spec};
#[derive(Parser, Debug)]
#[command(name = "tangible", version, about)]
pub struct Args {
pub input: PathBuf,
#[arg(short = 'o', long = "output")]
pub output: Option<PathBuf>,
}
pub fn run<F: FileOps>(args: Args, files: &F) -> Result<()> {
let json = files
.read_to_string(&args.input)
.with_context(|| format!("reading spec from {}", args.input.display()))?;
let spec: Spec = serde_json::from_str(&json)
.with_context(|| format!("parsing spec at {}", args.input.display()))?;
let manifest = Renderer::new()
.render(&spec)
.context("rendering manifest")?;
if let Some(path) = args.output {
if let Some(parent) = path.parent() {
if !parent.as_os_str().is_empty() {
files
.create_dir_all(parent)
.with_context(|| format!("creating {}", parent.display()))?;
}
}
files
.write(&path, manifest.as_str().as_bytes())
.with_context(|| format!("writing to {}", path.display()))?;
} else {
let stdout = io::stdout();
let mut handle = stdout.lock();
handle
.write_all(manifest.as_str().as_bytes())
.context("writing to stdout")?;
}
Ok(())
}