1use fancy_regex::Regex;
6use std::fmt::Display;
7use std::sync::OnceLock;
8
9fn get_expressions() -> &'static Vec<Regex> {
10 static EXPRESSIONS: OnceLock<Vec<Regex>> = OnceLock::new();
11 EXPRESSIONS.get_or_init(|| vec![Regex::new(r##"glpat-[0-9a-zA-Z\-_]*"##).unwrap()])
12}
13
14pub fn redact(input: &impl Display) -> String {
17 let mut copy = input.to_string();
18 for expr in get_expressions() {
19 copy = expr.replace_all(©, "LORRY_REDACTED").to_string();
20 }
21 copy
22}
23
24#[cfg(test)]
25mod tests {
26 use super::*;
27
28 struct TestCase<'a> {
29 pub input: &'a str,
30 pub expected: &'a str,
31 }
32
33 impl TestCase<'_> {
34 pub fn check(&self) {
35 let result = redact(&self.input.to_string());
36 assert!(result == self.expected);
37 }
38 }
39
40 #[test]
41 fn test_redact() {
42 TestCase {
43 input: "glpat-Y38-kU_3pviux6H1D9ec",
44 expected: "LORRY_REDACTED",
45 }
46 .check();
47 TestCase {
48 input: "glpat-AdmAbJdT-FMYPa_2bQyy",
49 expected: "LORRY_REDACTED",
50 }
51 .check();
52 TestCase {
53 input: "glpat-MjW2FqijnvVBs7yPEoDG",
54 expected: "LORRY_REDACTED",
55 }
56 .check();
57 TestCase {
58 input: "Using git binary to push remote: http://oauth2:glpat-25HjHgcpRJsY_JQweJYa@localhost:9999/lorry-mirrors/test/lorry.git",
59 expected: "Using git binary to push remote: http://oauth2:LORRY_REDACTED@localhost:9999/lorry-mirrors/test/lorry.git",
60 }.check();
61 }
62}