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