use rustledger_parser::format::format_source;
use std::env;
use std::fs;
use std::path::{Path, PathBuf};
fn main() {
let cases_dir = Path::new(env!("CARGO_MANIFEST_DIR"))
.join("tests")
.join("format_compat")
.join("cases");
if !cases_dir.is_dir() {
eprintln!("error: cases dir not found: {}", cases_dir.display());
std::process::exit(1);
}
let overwrite_all = env::var("BOOTSTRAP_OVERWRITE").as_deref() == Ok("1");
let target_fixture = env::var("BOOTSTRAP_FIXTURE").ok();
let mut fixtures: Vec<PathBuf> = fs::read_dir(&cases_dir)
.unwrap_or_else(|e| panic!("read_dir({}): {e}", cases_dir.display()))
.map(|entry| {
entry.unwrap_or_else(|e| {
panic!("read_dir entry under {} failed: {e}", cases_dir.display())
})
})
.map(|e| e.path())
.filter(|p| p.is_dir())
.collect();
fixtures.sort();
if let Some(name) = &target_fixture {
let dir = fixtures
.iter()
.find(|p| p.file_name().is_some_and(|f| f == name.as_str()));
let Some(dir) = dir else {
eprintln!(
"error: BOOTSTRAP_FIXTURE={name} does not match any directory in {}",
cases_dir.display(),
);
std::process::exit(2);
};
if !dir.join("input.bean").is_file() {
eprintln!(
"error: BOOTSTRAP_FIXTURE={name} resolves to {} but that directory has no input.bean. \
Add the source-text fixture before bootstrapping the expected.",
dir.display(),
);
std::process::exit(3);
}
}
let mut wrote = 0;
let mut skipped_existing = 0;
let mut skipped_unselected = 0;
let mut missing_input = 0;
for fixture in &fixtures {
let name = fixture.file_name().unwrap().to_string_lossy().into_owned();
if let Some(target) = &target_fixture
&& &name != target
{
skipped_unselected += 1;
continue;
}
let input_path = fixture.join("input.bean");
let expected_path = fixture.join("expected.bean");
if !input_path.exists() {
eprintln!("[{name}] missing input.bean - skipped");
missing_input += 1;
continue;
}
let allowed_to_overwrite = overwrite_all || target_fixture.is_some();
if expected_path.exists() && !allowed_to_overwrite {
skipped_existing += 1;
continue;
}
let input = fs::read_to_string(&input_path)
.unwrap_or_else(|e| panic!("[{name}] read input.bean: {e}"));
let formatted = format_source(&input);
fs::write(&expected_path, &formatted)
.unwrap_or_else(|e| panic!("[{name}] write expected.bean: {e}"));
eprintln!("[{name}] wrote expected.bean ({} bytes)", formatted.len());
wrote += 1;
}
eprintln!(
"\nbootstrap summary: {wrote} written, {skipped_existing} skipped (expected.bean already present), {skipped_unselected} skipped (unselected by BOOTSTRAP_FIXTURE), {missing_input} missing input.bean",
);
if target_fixture.is_some() {
eprintln!(
"(BOOTSTRAP_FIXTURE was set - only the named fixture's expected.bean was rewritten.)"
);
} else if overwrite_all {
eprintln!(
"(BOOTSTRAP_OVERWRITE=1 was set - existing expected.bean files were rewritten across the whole suite. \
Review `git diff` carefully before committing.)"
);
} else if skipped_existing > 0 {
eprintln!(
"(set BOOTSTRAP_FIXTURE=<name> to re-baseline a single fixture, or \
BOOTSTRAP_OVERWRITE=1 to re-baseline all of them; the suite-wide \
rewrite is destructive - use sparingly.)"
);
}
}