Skip to main content

bctx_forge/awareness/
build.rs

1use super::{AwarenessMap, EcosystemAwareness};
2use once_cell::sync::Lazy;
3use regex::Regex;
4
5static ERROR_RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"error\[(\w+)\]:(.+)").unwrap());
6static WARNING_RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"warning:(.+)").unwrap());
7static FINISHED_RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"Finished .+ in ([\d.]+)s").unwrap());
8
9pub struct BuildAwareness;
10
11impl EcosystemAwareness for BuildAwareness {
12    fn matches(&self, program: &str, args: &[String]) -> bool {
13        let prog = program.split('/').next_back().unwrap_or(program);
14        let sub = args.first().map(|s| s.as_str()).unwrap_or("");
15        matches!(prog, "make" | "cmake" | "gradle" | "bazel")
16            || (prog == "cargo" && matches!(sub, "build" | "check" | "clippy"))
17            || (prog == "go" && matches!(sub, "build" | "vet"))
18    }
19
20    fn extract(&self, stdout: &str, stderr: &str, exit_code: i32) -> AwarenessMap {
21        let mut map = AwarenessMap::new("build", "compile");
22        map.insert("exit_code", exit_code.to_string());
23
24        let combined = format!("{stderr}\n{stdout}");
25        let error_count = ERROR_RE.captures_iter(&combined).count();
26        let warning_count = WARNING_RE.captures_iter(&combined).count();
27
28        map.insert("error_count", error_count.to_string());
29        map.insert("warning_count", warning_count.to_string());
30        map.insert("succeeded", (exit_code == 0).to_string());
31
32        if let Some(cap) = FINISHED_RE.captures(&combined) {
33            map.insert("build_time_secs", cap[1].to_string());
34        }
35
36        map
37    }
38}