-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathmain.rs
More file actions
108 lines (98 loc) · 3.49 KB
/
main.rs
File metadata and controls
108 lines (98 loc) · 3.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use lazy_static::lazy_static;
use rayon::prelude::*;
use regex::Regex;
use std::collections::HashMap;
use std::{io::BufRead, process::Command};
// A map from filenames to lists of line numbers (for just the lines with deprecations)
type FileDeprecations = HashMap<String, Vec<String>>;
fn get_filename_and_lineno(line: &str) -> (String, String) {
let mut parts = line.splitn(3, ':');
let file = parts.next().unwrap().to_string();
let lineno = parts.next().unwrap().to_string();
(file, lineno)
}
#[test]
fn test_get_filename_and_lineno() {
let line = "path/to/file.ql:61:deprecated class Foo = Bar;";
let (file, lineno) = get_filename_and_lineno(line);
assert_eq!(file, "path/to/file.ql");
assert_eq!(lineno, "61");
}
fn get_files_with_deprecations() -> FileDeprecations {
let output = Command::new("git")
.args(&[
"grep",
"-n",
"-E",
"^[^*]*deprecated", // skip lines that have a `*` before `deprecated`, as they are probably comments
"--",
"*.ql",
"*.qll",
])
.output()
.expect("failed to execute process");
let mut file_deprecations: FileDeprecations = HashMap::new();
for line in output.stdout.lines() {
let (file, lineno) = get_filename_and_lineno(&line.unwrap());
file_deprecations
.entry(file)
.or_insert_with(Vec::new)
.push(lineno);
}
file_deprecations
}
struct LastModifiedLine {
date: String,
lineno: String,
}
type LastModifiedMap = HashMap<String, Vec<String>>;
fn get_blame_dates_for_filedeprecation(file: &str, linenos: &[String]) -> LastModifiedMap {
let mut command = Command::new("git");
command.arg("blame");
for lineno in linenos {
command.arg("-L").arg(format!("{},{}", lineno, lineno));
}
command.arg(file);
let output = command.output().expect("failed to execute process");
let mut blame_dates = HashMap::new();
for line in output.stdout.lines() {
let line = line.unwrap();
let LastModifiedLine { date, lineno } = get_last_modified(&line);
blame_dates
.entry(date)
.or_insert_with(Vec::new)
.push(lineno);
}
blame_dates
}
lazy_static! {
static ref BLAME_RE: Regex =
Regex::new("(\\d{4}-\\d{2}-\\d{2}).*[+-]\\d{4}\\s+(\\d+)\\)").unwrap();
}
fn get_last_modified(line: &str) -> LastModifiedLine {
let caps = BLAME_RE.captures(line).unwrap();
let date = caps.get(1).unwrap().as_str().into();
let lineno = caps.get(2).unwrap().as_str().into();
LastModifiedLine { date, lineno }
}
#[test]
fn test_get_date_and_lineno() {
let line = "cc7a9ef97a78 (john doe 2022-08-24 12:59:07 +0200 61) deprecated class Foo = Bar;";
let LastModifiedLine { date, lineno } = get_last_modified(line);
assert_eq!(date, "2022-08-24");
assert_eq!(lineno, "61");
}
fn main() {
let filedeprecations = get_files_with_deprecations();
let filedeprecations: Vec<(String, Vec<String>)> = filedeprecations.into_iter().collect();
println!("today: {}", chrono::Local::now().format("%Y-%m-%d"));
let deprecations = filedeprecations
.par_iter()
.map(|(file, linenos)| (file, get_blame_dates_for_filedeprecation(file, linenos)));
deprecations.for_each(|(file, linenos_and_dates)| {
println!("file: {}", file);
for (date, linenos) in linenos_and_dates.iter() {
println!(" last_modified: {} {}", date, linenos.join(" "));
}
});
}