use std::path::PathBuf;
use anyhow::{Result, bail};
use clap::{Parser, Subcommand};
use config_forge::{Format, check_convert_path, convert_path, inspect_path};
#[derive(Debug, Parser)]
#[command(name = "config-forge")]
#[command(version, about = config_forge::describe())]
struct Cli {
#[command(subcommand)]
command: Option<Command>,
}
#[derive(Debug, Subcommand)]
enum Command {
Convert {
input: PathBuf,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long, value_parser = parse_format)]
from: Option<Format>,
#[arg(long, value_parser = parse_format)]
to: Option<Format>,
#[arg(long)]
check: bool,
#[arg(long)]
overwrite: bool,
},
Inspect {
input: PathBuf,
#[arg(long, value_parser = parse_format)]
from: Option<Format>,
},
}
fn main() -> Result<()> {
let cli = Cli::parse();
match cli.command {
Some(Command::Convert {
input,
output,
from,
to,
check,
overwrite,
}) => convert(input, output, from, to, check, overwrite),
Some(Command::Inspect { input, from }) => inspect(input, from),
None => {
println!("{} {}", config_forge::NAME, config_forge::VERSION);
println!("{}", config_forge::describe());
Ok(())
}
}
}
fn convert(
input: PathBuf,
output: Option<PathBuf>,
from: Option<Format>,
to: Option<Format>,
check: bool,
overwrite: bool,
) -> Result<()> {
if check {
let output_format = check_convert_path(&input, from, to)?;
println!("ok: conversion to {} is valid", output_format.name());
return Ok(());
}
if output.is_none() && to.is_none() {
bail!("--to is required when --output is not provided");
}
let rendered = convert_path(&input, output.as_ref(), from, to, overwrite)?;
if output.is_none() {
print!("{rendered}");
}
Ok(())
}
fn inspect(input: PathBuf, from: Option<Format>) -> Result<()> {
let info = inspect_path(&input, from)?;
println!("path: {}", input.display());
println!("format: {}", info.format.name());
println!("root: {}", info.root_kind);
println!("size: {} bytes", info.size_bytes);
Ok(())
}
fn parse_format(value: &str) -> Result<Format> {
value.parse()
}