use std::path::PathBuf;
use anyhow::Result;
use clap::{Parser, Subcommand};
use unity_assetdb::bake::{BakeOptions, bake};
use unity_assetdb::walk::resolve_project_root;
#[derive(Parser)]
#[command(name = "unity-assetdb", about = "Unity asset GUID → name index baker.")]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
Bake {
#[arg(long)]
project: Option<PathBuf>,
#[arg(long)]
out_dir: Option<PathBuf>,
#[arg(long, value_name = "CHARS")]
scrub_chars: Option<String>,
},
}
fn main() -> Result<()> {
let cli = Cli::parse();
match cli.command {
Commands::Bake {
project,
out_dir,
scrub_chars,
} => {
let project_root = resolve_project_root(project.as_deref())?;
let out_dir =
out_dir.unwrap_or_else(|| project_root.join("Library").join("unity-assetdb"));
let verbose_timing = std::env::var("UNITY_ASSETDB_TIMING").is_ok();
let verbose_collisions = std::env::var("UNITY_ASSETDB_VERBOSE").is_ok();
let name_sanitizer = scrub_chars.map(|chars| {
let scrub: Vec<char> = chars.chars().collect();
let sanitizer: unity_assetdb::bake::NameSanitizer =
Box::new(move |s: &str| scrub_chars_in(s, &scrub));
sanitizer
});
let opts = BakeOptions {
project_root,
out_dir,
name_sanitizer,
on_warn: Some(Box::new(|m| eprintln!("{m}"))),
on_progress: Some(Box::new(|m| eprintln!("{m}"))),
verbose_timing,
verbose_collisions,
};
bake(&opts)?;
}
}
Ok(())
}
fn scrub_chars_in(name: &str, scrub: &[char]) -> Option<String> {
let first = name.char_indices().find(|(_, c)| scrub.contains(c))?;
let mut out = String::with_capacity(name.len());
out.push_str(&name[..first.0]);
out.push('_');
for c in name[first.0 + first.1.len_utf8()..].chars() {
out.push(if scrub.contains(&c) { '_' } else { c });
}
Some(out)
}