Skip to main content

run/
output.rs

1use regex::Regex;
2
3pub fn format_stderr(language: &str, stderr: &str, success: bool) -> String {
4    if stderr.trim().is_empty() {
5        return String::new();
6    }
7
8    let (scrubbed, _changed) = scrub_temp_paths(stderr);
9    if success {
10        return scrubbed;
11    }
12
13    format!("Error: {language} failed\n{scrubbed}")
14}
15
16fn scrub_temp_paths(stderr: &str) -> (String, bool) {
17    let mut changed = false;
18    let temp_dir = std::env::temp_dir();
19    let temp = temp_dir.to_string_lossy();
20
21    let mut output = stderr.to_string();
22    if output.contains(temp.as_ref()) {
23        output = output.replace(temp.as_ref(), "<temp>");
24        changed = true;
25    }
26
27    if temp.as_ref().starts_with("/var/") {
28        let private = format!("/private{temp}");
29        if output.contains(&private) {
30            output = output.replace(&private, "<temp>");
31            changed = true;
32        }
33    }
34
35    let re = Regex::new(r"<temp>/?(?:run-[^/]+|\.tmp[^/]+|run-[^/]+[^/]*)/").unwrap();
36    if re.is_match(&output) {
37        output = re.replace_all(&output, "<snippet>/").to_string();
38        changed = true;
39    }
40
41    let re_noslash = Regex::new(r"<temp>\.tmp[^/]+/").unwrap();
42    if re_noslash.is_match(&output) {
43        output = re_noslash.replace_all(&output, "<snippet>/").to_string();
44        changed = true;
45    }
46
47    (output, changed)
48}