From 598e983a8ed4ed2e0ae1081b7e0f5e41f9da6c3d Mon Sep 17 00:00:00 2001 From: Valentin Popov Date: Sat, 18 Jul 2026 06:06:08 +0400 Subject: [PATCH] feat(xtask): persist corpus baseline reports --- xtask/src/main.rs | 80 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 66 insertions(+), 14 deletions(-) diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 7814358..e2f4a53 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -127,15 +127,10 @@ fn run(args: &[String]) -> Result<(), String> { run_stage_tests(options.stage, TestSuite::Licensed, Some(&roots)) } [cmd, subcmd, rest @ ..] if cmd == "corpus" && subcmd == "baseline" => { - let root = parse_root(rest)?; - let manifest = - discover(&root, DiscoverOptions::default()).map_err(|e| e.to_string())?; - let report = report(&root, &manifest).map_err(|e| e.to_string())?; - println!("{}", render_report_json(&report)); - Ok(()) + run_corpus_baseline(&parse_corpus_baseline_options(rest)?) } _ => Err( - "usage: cargo xtask ci | policy | shader-provenance | acceptance report --suite synthetic|licensed [--stage 0..5|all] [--manifest corpora.toml] [--out ] | acceptance audit [--roadmap ] [--coverage ] [--out ] [--strict] | native-smoke audit --dir [--expected-commit ] [--expected-shader-manifest-hash ] | package --target --app viewer|game|headless|cli | test synthetic|licensed [--stage 0..5|all] [--manifest corpora.toml] | corpus baseline --root " + "usage: cargo xtask ci | policy | shader-provenance | acceptance report --suite synthetic|licensed [--stage 0..5|all] [--manifest corpora.toml] [--out ] | acceptance audit [--roadmap ] [--coverage ] [--out ] [--strict] | native-smoke audit --dir [--expected-commit ] [--expected-shader-manifest-hash ] | package --target --app viewer|game|headless|cli | test synthetic|licensed [--stage 0..5|all] [--manifest corpora.toml] | corpus baseline --root [--out ]" .to_string(), ), } @@ -754,17 +749,56 @@ fn validate_licensed_part(kind: &str, root: &Path) -> Result<(), String> { } } -fn parse_root(args: &[String]) -> Result { +#[derive(Clone, Debug, Eq, PartialEq)] +struct CorpusBaselineOptions { + root: PathBuf, + out: Option, +} + +fn parse_corpus_baseline_options(args: &[String]) -> Result { + let mut root = None; + let mut out = None; let mut iter = args.iter(); while let Some(arg) = iter.next() { - if arg == "--root" { - return iter - .next() - .map(PathBuf::from) - .ok_or_else(|| "--root requires a path".to_string()); + match arg.as_str() { + "--root" => { + root = Some( + iter.next() + .map(PathBuf::from) + .ok_or_else(|| "--root requires a path".to_string())?, + ); + } + "--out" => { + out = Some( + iter.next() + .map(PathBuf::from) + .ok_or_else(|| "--out requires a path".to_string())?, + ); + } + other => return Err(format!("unknown corpus baseline option: {other}")), } } - Err("missing --root".to_string()) + Ok(CorpusBaselineOptions { + root: root.ok_or_else(|| "missing --root".to_string())?, + out, + }) +} + +fn run_corpus_baseline(options: &CorpusBaselineOptions) -> Result<(), String> { + let manifest = + discover(&options.root, DiscoverOptions::default()).map_err(|error| error.to_string())?; + let baseline = report(&options.root, &manifest).map_err(|error| error.to_string())?; + let json = render_report_json(&baseline); + if let Some(out) = &options.out { + if let Some(parent) = out.parent() { + fs::create_dir_all(parent).map_err(|error| format!("{}: {error}", parent.display()))?; + } + fs::write(out, json).map_err(|error| format!("{}: {error}", out.display()))?; + println!("{}", out.display()); + } else { + println!("{json}"); + } + Ok(()) } #[derive(Clone, Debug, Eq, PartialEq)] @@ -3008,6 +3042,24 @@ mod tests { ); } + #[test] + fn parses_corpus_baseline_output_option() { + let options = parse_corpus_baseline_options(&strings(&[ + "--root", + "C:/GOG Games/Parkan - Iron Strategy", + "--out", + "target/fparkan/corpus/part1.json", + ])); + + assert_eq!( + options, + Ok(CorpusBaselineOptions { + root: PathBuf::from("C:/GOG Games/Parkan - Iron Strategy"), + out: Some(PathBuf::from("target/fparkan/corpus/part1.json")), + }) + ); + } + #[test] fn parses_acceptance_report_options() { let parsed = parse_acceptance_options(&strings(&[