@@ -0,0 +1,133 @@
1+use std::collections::HashMap;
2+use std::fs::File;
3+use std::io::{self, BufRead};
4+use std::path::Path;
5+
6+use regex::Regex;
7+
8+type H = HashMap<Header, Vec<(String, String, String)>>;
9+
10+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
11+enum Header {
12+ Versioned { package: String, version: String },
13+ Missing { package: String },
14+}
15+
16+fn main() {
17+ let mut lib_exes: H = Default::default();
18+ let mut tests: H = Default::default();
19+ let mut benches: H = Default::default();
20+ let mut last_header: Option<Header> = None;
21+ let empty = Regex::new(r#"^\s*$"#).unwrap();
22+ let header_versioned =
23+ Regex::new(r#"^(?P<package>[a-zA-z]([a-zA-z0-9.-]*?))-(?P<version>(\d+(\.\d+)*)).+?is out of bounds for:$"#).unwrap();
24+ let header_missing =
25+ Regex::new(r#"^(?P<package>[a-zA-z]([a-zA-z0-9.-]*)).+?depended on by:$"#).unwrap();
26+ let package =
27+ Regex::new(r#"^- \[ \] (?P<package>[a-zA-z]([a-zA-z0-9.-]*?))-(?P<version>(\d+(\.\d+)*)).+?Used by: (?P<component>.+)$"#)
28+ .unwrap();
29+
30+ if let Ok(lines) = read_lines("./comments.txt") {
31+ for line in lines {
32+ if let Ok(line) = line {
33+ if empty.captures(&line).is_some() {
34+ } else if let Some(cap) = package.captures(&line) {
35+ let root = last_header.clone().unwrap();
36+ let package = cap.name("package").unwrap().as_str();
37+ let version = cap.name("version").unwrap().as_str();
38+ let component = cap.name("component").unwrap().as_str();
39+ match component {
40+ "library" | "executable" => {
41+ insert(&mut lib_exes, root, package, version, component)
42+ }
43+ "benchmark" => insert(&mut benches, root, package, version, "benchmarks"),
44+ "test-suite" => insert(&mut tests, root, package, version, component),
45+ _ => panic!("Bad component: {}", component),
46+ }
47+ } else if let Some(cap) = header_versioned.captures(&line) {
48+ let package = cap.name("package").unwrap().as_str().to_owned();
49+ let version = cap.name("version").unwrap().as_str().to_owned();
50+ last_header = Some(Header::Versioned { package, version });
51+ } else if let Some(cap) = header_missing.captures(&line) {
52+ let package = cap.name("package").unwrap().as_str().to_owned();
53+ last_header = Some(Header::Missing { package });
54+ } else {
55+ panic!("Unhandled: {:?}", line);
56+ }
57+ }
58+ }
59+ }
60+
61+ if !lib_exes.is_empty() {
62+ println!("\nLIBS + EXES\n");
63+ }
64+ for (header, packages) in lib_exes {
65+ for (package, version, component) in packages {
66+ printer(" ", &package, true, &version, &component, &header);
67+ }
68+ }
69+
70+ if !tests.is_empty() {
71+ println!("\nTESTS\n");
72+ }
73+ for (header, packages) in tests {
74+ for (package, version, component) in packages {
75+ printer(" ", &package, false, &version, &component, &header);
76+ }
77+ }
78+
79+ if !benches.is_empty() {
80+ println!("\nBENCHMARKS\n");
81+ }
82+ for (header, packages) in benches {
83+ for (package, version, component) in packages {
84+ printer(" ", &package, false, &version, &component, &header);
85+ }
86+ }
87+}
88+
89+fn printer(
90+ indent: &str,
91+ package: &str,
92+ lt0: bool,
93+ version: &str,
94+ component: &str,
95+ header: &Header,
96+) -> () {
97+ let lt0 = if lt0 { " < 0" } else { "" };
98+ println!(
99+ "{indent}- {package}{lt0} # tried {package}-{version}, but its *{component}* {cause}",
100+ indent = indent,
101+ package = package,
102+ lt0 = lt0,
103+ version = version,
104+ component = component,
105+ cause = match header {
106+ Header::Versioned { package, version } => format!(
107+ "does not support: {package}-{version}",
108+ package = package,
109+ version = version
110+ ),
111+ Header::Missing { package } => format!(
112+ "requires the disabled package: {package}",
113+ package = package
114+ ),
115+ },
116+ );
117+}
118+
119+fn insert(h: &mut H, header: Header, package: &str, version: &str, component: &str) {
120+ (*h.entry(header).or_insert_with(|| vec![])).push((
121+ package.to_owned(),
122+ version.to_owned(),
123+ component.to_owned(),
124+ ));
125+}
126+
127+fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
128+where
129+ P: AsRef<Path>,
130+{
131+ let file = File::open(filename)?;
132+ Ok(io::BufReader::new(file).lines())
133+}