blob: f225104bda9258fd0340249f479765d21220c82f [file] [log] [blame]
#![cfg_attr(feature = "build-metrics", allow(unused))]
use std::str::FromStr;
use std::path::PathBuf;
use clap::Parser;
use crate::{builder::Builder, tool::Tool};
/// Suggests a list of possible `x.py` commands to run based on modified files in branch.
pub fn suggest(builder: &Builder<'_>, run: bool) {
let suggestions =
builder.tool_cmd(Tool::SuggestTests).output().expect("failed to run `suggest-tests` tool");
if !suggestions.status.success() {
println!("failed to run `suggest-tests` tool ({})", suggestions.status);
println!(
"`suggest_tests` stdout:\n{}`suggest_tests` stderr:\n{}",
String::from_utf8(suggestions.stdout).unwrap(),
String::from_utf8(suggestions.stderr).unwrap()
);
panic!("failed to run `suggest-tests`");
}
let suggestions = String::from_utf8(suggestions.stdout).unwrap();
let suggestions = suggestions
.lines()
.map(|line| {
let mut sections = line.split_ascii_whitespace();
// this code expects one suggestion per line in the following format:
// <x_subcommand> {some number of flags} [optional stage number]
let cmd = sections.next().unwrap();
let stage = sections.next_back().map(|s| str::parse(s).ok()).flatten();
let paths: Vec<PathBuf> = sections.map(|p| PathBuf::from_str(p).unwrap()).collect();
(cmd, stage, paths)
})
.collect::<Vec<_>>();
if !suggestions.is_empty() {
println!("==== SUGGESTIONS ====");
for sug in &suggestions {
print!("x {} ", sug.0);
if let Some(stage) = sug.1 {
print!("--stage {stage} ");
}
for path in &sug.2 {
print!("{} ", path.display());
}
println!();
}
println!("=====================");
} else {
println!("No suggestions found!");
return;
}
if run {
for sug in suggestions {
let mut build: crate::Build = builder.build.clone();
build.config.paths = sug.2;
build.config.cmd = crate::flags::Flags::parse_from(["x.py", sug.0]).cmd;
if let Some(stage) = sug.1 {
build.config.stage = stage;
}
build.build();
}
} else {
println!("help: consider using the `--run` flag to automatically run suggested tests");
}
}