use clap::Parser;
use clap_verbosity_flag::{Verbosity, WarnLevel};
use env_logger::Target;
use putter::{FilesState, Manifest};
use std::path::{Path, PathBuf};
#[derive(Debug, clap::Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
#[command(flatten)]
verbose: Verbosity<WarnLevel>,
#[command(subcommand)]
command: Option<Command>,
}
#[derive(Debug, clap::Subcommand)]
enum Command {
Apply {
manifest_file: PathBuf,
#[arg(long)]
state_file: PathBuf,
#[arg(short = 'n', long, default_value_t = false)]
dry_run: bool,
},
Check {
manifest_file: PathBuf,
#[arg(long)]
state_file: PathBuf,
},
}
fn apply(manifest_file: PathBuf, state_file: PathBuf, dry_run: bool) -> anyhow::Result<()> {
let manifest = Manifest::load(manifest_file)?;
let state = if state_file.try_exists()? {
FilesState::load(&state_file)?
} else {
FilesState::EMPTY
};
let manifest = manifest.into_manifest_low()?;
if dry_run {
putter::apply_dry_run(&state, &manifest)?;
} else {
let state = putter::apply(&state, &manifest)?;
state.save(state_file)?;
}
Ok(())
}
fn check(manifest_file: PathBuf, state_file: &Path) -> anyhow::Result<()> {
let manifest = Manifest::load(manifest_file)?;
let state = if state_file.try_exists()? {
FilesState::load(state_file)?
} else {
FilesState::EMPTY
};
let manifest = manifest.into_manifest_low()?;
putter::check(&state, &manifest)?;
Ok(())
}
fn main() -> anyhow::Result<()> {
let cli = Cli::parse();
env_logger::Builder::new()
.filter_level(cli.verbose.log_level_filter())
.target(Target::Stdout)
.format_level(false)
.format_target(false)
.init();
match cli.command {
Some(Command::Apply {
manifest_file,
state_file,
dry_run,
}) => apply(manifest_file, state_file, dry_run),
Some(Command::Check {
manifest_file,
state_file,
}) => check(manifest_file, &state_file),
None => Ok(()),
}
}