mirror of
https://github.com/commercialhaskell/stackage.git
synced 2026-01-15 08:48:31 +01:00
207 lines
6.1 KiB
Rust
207 lines
6.1 KiB
Rust
use std::collections::{BTreeMap, BTreeSet};
|
|
use std::fs::File;
|
|
use std::io::{BufRead, BufReader, LineWriter, Lines, Write};
|
|
use std::path::Path;
|
|
use std::process::Command;
|
|
|
|
use lazy_regex::regex;
|
|
|
|
pub fn clear() {
|
|
handle(true, |loc, _lines| match loc {
|
|
// Add empty array to keep yaml valid
|
|
Location::Lib => vec![" []".to_owned()],
|
|
Location::Test | Location::Bench => vec![],
|
|
});
|
|
}
|
|
|
|
pub fn add(lib: Vec<String>, test: Vec<String>, bench: Vec<String>) {
|
|
handle(true, |loc, mut lines| {
|
|
lines.extend(match loc {
|
|
Location::Lib => lib.clone(),
|
|
Location::Test => test.clone(),
|
|
Location::Bench => bench.clone(),
|
|
});
|
|
lines.sort();
|
|
lines
|
|
})
|
|
}
|
|
|
|
pub fn outdated() {
|
|
let mut all = vec![];
|
|
handle(false, |_loc, lines| {
|
|
all.extend(lines);
|
|
vec![]
|
|
});
|
|
let mut map = BTreeMap::new();
|
|
let mut support: BTreeMap<(String, String), BTreeSet<(String, String)>> = BTreeMap::new();
|
|
for v in all.into_iter() {
|
|
let caps = regex!("tried ([^ ]+)-([^,-]+),").captures(&v).unwrap();
|
|
let package = caps.get(1).unwrap().as_str().to_owned();
|
|
let version = caps.get(2).unwrap().as_str().to_owned();
|
|
map.insert(package.clone(), version.clone());
|
|
|
|
if let Some(caps) = regex!("does not support: ([^ ]+)-([^-]+)").captures(&v) {
|
|
let dep_package = caps.get(1).unwrap().as_str().to_owned();
|
|
let dep_version = caps.get(2).unwrap().as_str().to_owned();
|
|
let entry = support
|
|
.entry((dep_package, dep_version))
|
|
.or_default();
|
|
entry.insert((package, version));
|
|
}
|
|
}
|
|
|
|
let entries = map.len() + support.len();
|
|
let mut i = 0;
|
|
|
|
for (package, version) in map {
|
|
if i % 100 == 0 {
|
|
println!("{:02}%", ((i as f64 / entries as f64) * 100.0).floor());
|
|
}
|
|
i += 1;
|
|
let latest = latest_version(&package);
|
|
if version != latest {
|
|
println!(
|
|
"{} mismatch, snapshot: {}, hackage: {}",
|
|
package, version, latest
|
|
);
|
|
}
|
|
}
|
|
|
|
for ((package, version), dependents) in support {
|
|
if i % 100 == 0 {
|
|
println!("{:02}%", ((i as f64 / entries as f64) * 100.0).floor());
|
|
}
|
|
i += 1;
|
|
let latest = latest_version(&package);
|
|
if version != latest {
|
|
println!(
|
|
"{} mismatch, snapshot: {}, hackage: {}, dependents: {}",
|
|
package,
|
|
version,
|
|
latest,
|
|
dependents
|
|
.into_iter()
|
|
.map(|(p, v)| format!("{}-{}", p, v))
|
|
.collect::<Vec<String>>()
|
|
.join(", "),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn latest_version(pkg: &str) -> String {
|
|
String::from_utf8(
|
|
Command::new("latest-version")
|
|
.args([pkg])
|
|
.output()
|
|
.unwrap()
|
|
.stdout,
|
|
)
|
|
.unwrap()
|
|
.trim()
|
|
.to_owned()
|
|
}
|
|
|
|
enum State {
|
|
LookingForLibBounds,
|
|
ProcessingLibBounds,
|
|
LookingForTestBounds,
|
|
ProcessingTestBounds,
|
|
LookingForBenchBounds,
|
|
ProcessingBenchBounds,
|
|
Done,
|
|
}
|
|
|
|
fn handle<F>(write: bool, mut f: F)
|
|
where
|
|
F: FnMut(Location, Vec<String>) -> Vec<String>,
|
|
{
|
|
let path = "build-constraints.yaml";
|
|
let mut new_lines: Vec<String> = vec![];
|
|
|
|
let mut state = State::LookingForLibBounds;
|
|
let mut buf = vec![];
|
|
for line in read_lines(path).map(|s| s.unwrap()) {
|
|
match state {
|
|
State::LookingForLibBounds => {
|
|
if line == r#" "Library and exe bounds failures":"# {
|
|
state = State::ProcessingLibBounds;
|
|
}
|
|
new_lines.push(line);
|
|
}
|
|
State::ProcessingLibBounds => {
|
|
if line == r#" # End of Library and exe bounds failures"# {
|
|
new_lines.extend(f(Location::Lib, buf).into_iter());
|
|
buf = vec![];
|
|
new_lines.push(line);
|
|
state = State::LookingForTestBounds;
|
|
} else {
|
|
// Remove empty section
|
|
if line != " []" {
|
|
buf.push(line);
|
|
}
|
|
}
|
|
}
|
|
State::LookingForTestBounds => {
|
|
if line == r#" # Test bounds issues"# {
|
|
state = State::ProcessingTestBounds;
|
|
}
|
|
new_lines.push(line);
|
|
}
|
|
State::ProcessingTestBounds => {
|
|
if line == r#" # End of Test bounds issues"# {
|
|
new_lines.extend(f(Location::Test, buf).into_iter());
|
|
buf = vec![];
|
|
new_lines.push(line);
|
|
state = State::LookingForBenchBounds;
|
|
} else {
|
|
buf.push(line);
|
|
}
|
|
}
|
|
State::LookingForBenchBounds => {
|
|
if line == r#" # Benchmark bounds issues"# {
|
|
state = State::ProcessingBenchBounds;
|
|
}
|
|
new_lines.push(line);
|
|
}
|
|
State::ProcessingBenchBounds => {
|
|
if line == r#" # End of Benchmark bounds issues"# {
|
|
new_lines.extend(f(Location::Bench, buf).into_iter());
|
|
buf = vec![];
|
|
new_lines.push(line);
|
|
state = State::Done;
|
|
} else {
|
|
buf.push(line);
|
|
}
|
|
}
|
|
State::Done => {
|
|
new_lines.push(line);
|
|
}
|
|
}
|
|
}
|
|
|
|
if write {
|
|
let file = File::create(path).unwrap();
|
|
let mut file = LineWriter::new(file);
|
|
|
|
for line in new_lines {
|
|
file.write_all((line + "\n").as_bytes()).unwrap();
|
|
}
|
|
file.flush().unwrap();
|
|
}
|
|
}
|
|
|
|
enum Location {
|
|
Lib,
|
|
Test,
|
|
Bench,
|
|
}
|
|
|
|
fn read_lines<P>(filename: P) -> Lines<BufReader<File>>
|
|
where
|
|
P: AsRef<Path>,
|
|
{
|
|
let file = File::open(filename).unwrap();
|
|
BufReader::new(file).lines()
|
|
}
|