on 010fd11 help sign in
206 lines 6.2 kB history raw
1use std::collections::{BTreeMap, BTreeSet};
2use std::fs::File;
3use std::io::{BufRead, BufReader, LineWriter, Lines, Write};
4use std::path::Path;
5use std::process::Command;
7use lazy_regex::regex;
9pub fn clear() {
10 handle(true, |loc, _lines| match loc {
11 // Add empty array to keep yaml valid
12 Location::Lib => vec![" []".to_owned()],
13 Location::Test | Location::Bench => vec![],
14 });
17pub fn add(lib: Vec<String>, test: Vec<String>, bench: Vec<String>) {
18 handle(true, |loc, mut lines| {
19 lines.extend(match loc {
20 Location::Lib => lib.clone(),
21 Location::Test => test.clone(),
22 Location::Bench => bench.clone(),
23 });
24 lines.sort();
25 lines
26 })
29pub fn outdated() {
30 let mut all = vec![];
31 handle(false, |_loc, lines| {
32 all.extend(lines);
33 vec![]
34 });
35 let mut map = BTreeMap::new();
36 let mut support: BTreeMap<(String, String), BTreeSet<(String, String)>> = BTreeMap::new();
37 for v in all.into_iter() {
38 let caps = regex!("tried ([^ ]+)-([^,-]+),").captures(&v).unwrap();
39 let package = caps.get(1).unwrap().as_str().to_owned();
40 let version = caps.get(2).unwrap().as_str().to_owned();
41 map.insert(package.clone(), version.clone());
43 if let Some(caps) = regex!("does not support: ([^ ]+)-([^-]+)").captures(&v) {
44 let dep_package = caps.get(1).unwrap().as_str().to_owned();
45 let dep_version = caps.get(2).unwrap().as_str().to_owned();
46 let entry = support
47 .entry((dep_package, dep_version))
48 .or_default();
49 entry.insert((package, version));
50 }
51 }
53 let entries = map.len() + support.len();
54 let mut i = 0;
56 for (package, version) in map {
57 if i % 100 == 0 {
58 println!("{:02}%", ((i as f64 / entries as f64) * 100.0).floor());
59 }
60 i += 1;
61 let latest = latest_version(&package);
62 if version != latest {
63 println!(
64 "{} mismatch, snapshot: {}, hackage: {}",
65 package, version, latest
66 );
67 }
68 }
70 for ((package, version), dependents) in support {
71 if i % 100 == 0 {
72 println!("{:02}%", ((i as f64 / entries as f64) * 100.0).floor());
73 }
74 i += 1;
75 let latest = latest_version(&package);
76 if version != latest {
77 println!(
78 "{} mismatch, snapshot: {}, hackage: {}, dependents: {}",
79 package,
80 version,
81 latest,
82 dependents
83 .into_iter()
84 .map(|(p, v)| format!("{}-{}", p, v))
85 .collect::<Vec<String>>()
86 .join(", "),
87 );
88 }
89 }
92fn latest_version(pkg: &str) -> String {
93 String::from_utf8(
94 Command::new("latest-version")
95 .args([pkg])
96 .output()
97 .unwrap()
98 .stdout,
99 )
100 .unwrap()
101 .trim()
102 .to_owned()
105enum State {
106 LookingForLibBounds,
107 ProcessingLibBounds,
108 LookingForTestBounds,
109 ProcessingTestBounds,
110 LookingForBenchBounds,
111 ProcessingBenchBounds,
112 Done,
115fn handle<F>(write: bool, mut f: F)
116where
117 F: FnMut(Location, Vec<String>) -> Vec<String>,
119 let path = "build-constraints.yaml";
120 let mut new_lines: Vec<String> = vec![];
122 let mut state = State::LookingForLibBounds;
123 let mut buf = vec![];
124 for line in read_lines(path).map(|s| s.unwrap()) {
125 match state {
126 State::LookingForLibBounds => {
127 if line == r#" "Library and exe bounds failures":"# {
128 state = State::ProcessingLibBounds;
129 }
130 new_lines.push(line);
131 }
132 State::ProcessingLibBounds => {
133 if line == r#" # End of Library and exe bounds failures"# {
134 new_lines.extend(f(Location::Lib, buf).into_iter());
135 buf = vec![];
136 new_lines.push(line);
137 state = State::LookingForTestBounds;
138 } else {
139 // Remove empty section
140 if line != " []" {
141 buf.push(line);
142 }
143 }
144 }
145 State::LookingForTestBounds => {
146 if line == r#" # Test bounds issues"# {
147 state = State::ProcessingTestBounds;
148 }
149 new_lines.push(line);
150 }
151 State::ProcessingTestBounds => {
152 if line == r#" # End of Test bounds issues"# {
153 new_lines.extend(f(Location::Test, buf).into_iter());
154 buf = vec![];
155 new_lines.push(line);
156 state = State::LookingForBenchBounds;
157 } else {
158 buf.push(line);
159 }
160 }
161 State::LookingForBenchBounds => {
162 if line == r#" # Benchmark bounds issues"# {
163 state = State::ProcessingBenchBounds;
164 }
165 new_lines.push(line);
166 }
167 State::ProcessingBenchBounds => {
168 if line == r#" # End of Benchmark bounds issues"# {
169 new_lines.extend(f(Location::Bench, buf).into_iter());
170 buf = vec![];
171 new_lines.push(line);
172 state = State::Done;
173 } else {
174 buf.push(line);
175 }
176 }
177 State::Done => {
178 new_lines.push(line);
179 }
180 }
181 }
183 if write {
184 let file = File::create(path).unwrap();
185 let mut file = LineWriter::new(file);
187 for line in new_lines {
188 file.write_all((line + "\n").as_bytes()).unwrap();
189 }
190 file.flush().unwrap();
191 }
194enum Location {
195 Lib,
196 Test,
197 Bench,
200fn read_lines<P>(filename: P) -> Lines<BufReader<File>>
201where
202 P: AsRef<Path>,
204 let file = File::open(filename).unwrap();
205 BufReader::new(file).lines()